forked from GitHub/gf-core
Founding the newly structured GF2.0 cvs archive.
This commit is contained in:
12
bin/jgf2
Normal file
12
bin/jgf2
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# change the value of GFHOME to the directory where you have the gf binary
|
||||||
|
GFHOME=/home/aarne/GF2/bin
|
||||||
|
# /.../chalmers.se/fs/cab/cs/.users/markus/home/GF1
|
||||||
|
|
||||||
|
JGUILIB=$GFHOME/java/
|
||||||
|
GF=$GFHOME/gf2+
|
||||||
|
JGUI=GFEditor
|
||||||
|
|
||||||
|
java -cp $JGUILIB $JGUI "$GF -java $*"
|
||||||
|
|
||||||
63
grammars/logic/Arithm.gf
Normal file
63
grammars/logic/Arithm.gf
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
abstract Arithm = Logic ** {
|
||||||
|
|
||||||
|
-- arithmetic
|
||||||
|
fun
|
||||||
|
Nat, Real : Dom ;
|
||||||
|
zero : Elem Nat ;
|
||||||
|
succ : Elem Nat -> Elem Nat ;
|
||||||
|
|
||||||
|
trunc : Elem Real -> Elem Nat ;
|
||||||
|
|
||||||
|
EqNat : (m,n : Elem Nat) -> Prop ;
|
||||||
|
LtNat : (m,n : Elem Nat) -> Prop ;
|
||||||
|
Div : (m,n : Elem Nat) -> Prop ;
|
||||||
|
Even : Elem Nat -> Prop ;
|
||||||
|
Odd : Elem Nat -> Prop ;
|
||||||
|
Prime : Elem Nat -> Prop ;
|
||||||
|
|
||||||
|
one : Elem Nat ;
|
||||||
|
two : Elem Nat ;
|
||||||
|
sum : (m,n : Elem Nat) -> Elem Nat ;
|
||||||
|
prod : (m,n : Elem Nat) -> Elem Nat ;
|
||||||
|
|
||||||
|
evax1 : Proof (Even zero) ;
|
||||||
|
evax2 : (n : Elem Nat) -> Proof (Even n) -> Proof (Odd (succ n)) ;
|
||||||
|
evax3 : (n : Elem Nat) -> Proof (Odd n) -> Proof (Even (succ n)) ;
|
||||||
|
eqax1 : Proof (EqNat zero zero) ;
|
||||||
|
eqax2 : (m,n : Elem Nat) -> Proof (EqNat m n) -> Proof (EqNat (succ m) (succ n)) ;
|
||||||
|
|
||||||
|
IndNat : (C : Elem Nat -> Prop) ->
|
||||||
|
Proof (C zero) ->
|
||||||
|
((x : Elem Nat) -> Proof (C x) -> Proof (C (succ x))) ->
|
||||||
|
Proof (Univ Nat C) ;
|
||||||
|
|
||||||
|
def
|
||||||
|
one = succ zero ;
|
||||||
|
two = succ one ;
|
||||||
|
sum m zero = m ;
|
||||||
|
sum m (succ n) = succ (sum m n) ;
|
||||||
|
prod m zero = zero ;
|
||||||
|
prod m (succ n) = sum (prod m n) m ;
|
||||||
|
LtNat m n = Exist Nat (\x -> EqNat n (sum m (succ x))) ;
|
||||||
|
Div m n = Exist Nat (\x -> EqNat m (prod x n)) ;
|
||||||
|
Prime n = Conj
|
||||||
|
(LtNat one n)
|
||||||
|
(Univ Nat (\x -> Impl (Conj (LtNat one x) (Div n x)) (EqNat x n))) ;
|
||||||
|
|
||||||
|
fun ex1 : Text ;
|
||||||
|
def ex1 =
|
||||||
|
ThmWithProof
|
||||||
|
(Univ Nat (\x -> Disj (Even x) (Odd x)))
|
||||||
|
(IndNat
|
||||||
|
(\x -> Disj (Even x) (Odd x))
|
||||||
|
(DisjIl (Even zero) (Odd zero) evax1)
|
||||||
|
(\x -> \h -> DisjE (Even x) (Odd x) (Disj (Even (succ x)) (Odd (succ x)))
|
||||||
|
(Hypo (Disj (Even x) (Odd x)) h)
|
||||||
|
(\a -> DisjIr (Even (succ x)) (Odd (succ x))
|
||||||
|
(evax2 x (Hypo (Even x) a)))
|
||||||
|
(\b -> DisjIl (Even (succ x)) (Odd (succ x))
|
||||||
|
(evax3 x (Hypo (Odd x) b))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) ;
|
||||||
|
} ;
|
||||||
40
grammars/logic/ArithmEng.gf
Normal file
40
grammars/logic/ArithmEng.gf
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
concrete ArithmEng of Arithm = LogicEng ** open LogicResEng in {
|
||||||
|
|
||||||
|
lin
|
||||||
|
Nat = {s = nomReg "number"} ;
|
||||||
|
zero = ss "zero" ;
|
||||||
|
succ = fun1 "successor" ;
|
||||||
|
|
||||||
|
EqNat = adj2 ["equal to"] ;
|
||||||
|
LtNat = adj2 ["smaller than"] ;
|
||||||
|
Div = adj2 ["divisible by"] ;
|
||||||
|
Even = adj1 "even" ;
|
||||||
|
Odd = adj1 "odd" ;
|
||||||
|
Prime = adj1 "prime" ;
|
||||||
|
|
||||||
|
one = ss "one" ;
|
||||||
|
two = ss "two" ;
|
||||||
|
sum = fun2 "sum" ;
|
||||||
|
prod = fun2 "product" ;
|
||||||
|
|
||||||
|
evax1 = ss ["by the first axiom of evenness , zero is even"] ;
|
||||||
|
evax2 n c = {s =
|
||||||
|
c.s ++ [". By the second axiom of evenness , the successor of"] ++
|
||||||
|
n.s ++ ["is odd"]} ;
|
||||||
|
evax3 n c = {s =
|
||||||
|
c.s ++ [". By the third axiom of evenness , the successor of"] ++
|
||||||
|
n.s ++ ["is even"]} ;
|
||||||
|
eqax1 = ss ["by the first axiom of equality , zero is equal to zero"] ;
|
||||||
|
eqax2 m n c = {s =
|
||||||
|
c.s ++ [". By the second axiom of equality , the successor of"] ++ m.s ++
|
||||||
|
["is equal to the successor of"] ++ n.s} ;
|
||||||
|
IndNat C d e = {s =
|
||||||
|
["we proceed by induction . For the basis ,"] ++ d.s ++
|
||||||
|
[". For the induction step, consider a number"] ++ C.$0 ++
|
||||||
|
["and assume"] ++ C.s ++ "(" ++ e.$1 ++ ")" ++ "." ++ e.s ++
|
||||||
|
["Hence, for all numbers"] ++ C.$0 ++ "," ++ C.s} ;
|
||||||
|
|
||||||
|
ex1 = ss ["The first theorem and its proof ."] ;
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
82
grammars/logic/Logic.gf
Normal file
82
grammars/logic/Logic.gf
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
-- many-sorted predicate calculus
|
||||||
|
-- AR 1999, revised 2001
|
||||||
|
|
||||||
|
abstract Logic = {
|
||||||
|
|
||||||
|
flags startcat=Prop ; -- this is what you want to parse
|
||||||
|
|
||||||
|
cat
|
||||||
|
Prop ; -- proposition
|
||||||
|
Dom ; -- domain of quantification
|
||||||
|
Elem Dom ; -- individual element of a domain
|
||||||
|
Proof Prop ; -- proof of a proposition
|
||||||
|
Text ; -- theorem with proof etc.
|
||||||
|
|
||||||
|
fun
|
||||||
|
-- texts
|
||||||
|
Statement : Prop -> Text ;
|
||||||
|
ThmWithProof : (A : Prop) -> Proof A -> Text ;
|
||||||
|
ThmWithTrivialProof : (A : Prop) -> Proof A -> Text ;
|
||||||
|
|
||||||
|
-- logically complex propositions
|
||||||
|
Disj : (A,B : Prop) -> Prop ;
|
||||||
|
Conj : (A,B : Prop) -> Prop ;
|
||||||
|
Impl : (A,B : Prop) -> Prop ;
|
||||||
|
Abs : Prop ;
|
||||||
|
Neg : Prop -> Prop ;
|
||||||
|
|
||||||
|
Univ : (A : Dom) -> (Elem A -> Prop) -> Prop ;
|
||||||
|
Exist : (A : Dom) -> (Elem A -> Prop) -> Prop ;
|
||||||
|
|
||||||
|
-- progressive implication ŕ la type theory
|
||||||
|
ImplP : (A : Prop) -> (Proof A -> Prop) -> Prop ;
|
||||||
|
|
||||||
|
-- inference rules
|
||||||
|
ConjI : (A,B : Prop) -> Proof A -> Proof B -> Proof (Conj A B) ;
|
||||||
|
ConjEl : (A,B : Prop) -> Proof (Conj A B) -> Proof A ;
|
||||||
|
ConjEr : (A,B : Prop) -> Proof (Conj A B) -> Proof B ;
|
||||||
|
DisjIl : (A,B : Prop) -> Proof A -> Proof (Disj A B) ;
|
||||||
|
DisjIr : (A,B : Prop) -> Proof B -> Proof (Disj A B) ;
|
||||||
|
DisjE : (A,B,C : Prop) -> Proof (Disj A B) ->
|
||||||
|
(Proof A -> Proof C) -> (Proof B -> Proof C) -> Proof C ;
|
||||||
|
ImplI : (A,B : Prop) -> (Proof A -> Proof B) -> Proof (Impl A B) ;
|
||||||
|
ImplE : (A,B : Prop) -> Proof (Impl A B) -> Proof A -> Proof B ;
|
||||||
|
NegI : (A : Prop) -> (Proof A -> Proof Abs) -> Proof (Neg A) ;
|
||||||
|
NegE : (A : Prop) -> Proof (Neg A) -> Proof A -> Proof Abs ;
|
||||||
|
AbsE : (C : Prop) -> Proof Abs -> Proof C ;
|
||||||
|
|
||||||
|
UnivI : (A : Dom) -> (B : Elem A -> Prop) ->
|
||||||
|
((x : Elem A) -> Proof (B x)) -> Proof (Univ A B) ;
|
||||||
|
UnivE : (A : Dom) -> (B : Elem A -> Prop) ->
|
||||||
|
Proof (Univ A B) -> (a : Elem A) -> Proof (B a) ;
|
||||||
|
ExistI : (A : Dom) -> (B : Elem A -> Prop) ->
|
||||||
|
(a : Elem A) -> Proof (B a) -> Proof (Exist A B) ;
|
||||||
|
ExistE : (A : Dom) -> (B : Elem A -> Prop) -> (C : Prop) ->
|
||||||
|
Proof (Exist A B) -> ((x : Elem A) -> Proof (B x) -> Proof C) ->
|
||||||
|
Proof C ;
|
||||||
|
|
||||||
|
-- use a hypothesis
|
||||||
|
Hypo : (A : Prop) -> Proof A -> Proof A ;
|
||||||
|
|
||||||
|
-- pronoun
|
||||||
|
Pron : (A : Dom) -> Elem A -> Elem A ;
|
||||||
|
|
||||||
|
data
|
||||||
|
Proof = ConjI | DisjIl | DisjIr ;
|
||||||
|
|
||||||
|
def
|
||||||
|
-- proof normalization
|
||||||
|
ConjEl _ _ (ConjI _ _ a _) = a ;
|
||||||
|
ConjEr _ _ (ConjI _ _ _ b) = b ;
|
||||||
|
DisjE _ _ _ (DisjIl _ _ a) d _ = d a ;
|
||||||
|
DisjE _ _ _ (DisjIr _ _ b) _ e = e b ;
|
||||||
|
ImplE _ _ (ImplI _ _ b) a = b a ;
|
||||||
|
NegE _ (NegI _ b) a = b a ;
|
||||||
|
UnivE _ _ (UnivI _ _ b) a = b a ;
|
||||||
|
ExistE _ _ _ (ExistI _ _ a b) d = d a b ;
|
||||||
|
|
||||||
|
-- Hypo and Pron are identities
|
||||||
|
Hypo _ a = a ;
|
||||||
|
Pron _ a = a ;
|
||||||
|
|
||||||
|
} ;
|
||||||
59
grammars/logic/LogicEng.gf
Normal file
59
grammars/logic/LogicEng.gf
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
concrete LogicEng of Logic = open LogicResEng in {
|
||||||
|
|
||||||
|
flags lexer=vars ; unlexer=text ;
|
||||||
|
|
||||||
|
lincat
|
||||||
|
Dom = {s : Num => Str} ;
|
||||||
|
Prop, Elem = {s : Str} ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
Statement A = {s = A.s ++ "."} ;
|
||||||
|
ThmWithProof A a = {s = ["Theorem ."] ++ A.s ++ [". <p> Proof ."] ++ a.s ++ "."} ;
|
||||||
|
ThmWithTrivialProof A a =
|
||||||
|
{s = "Theorem" ++ "." ++ A.s ++ [". <p> Proof . Trivial ."]} ;
|
||||||
|
Disj A B = {s = A.s ++ "or" ++ B.s} ;
|
||||||
|
Conj A B = {s = A.s ++ "and" ++ B.s} ;
|
||||||
|
Impl A B = {s = "if" ++ A.s ++ "then" ++ B.s} ;
|
||||||
|
Univ A B = {s = ["for all"] ++ A.s ! pl ++ B.$0 ++ "," ++ B.s} ;
|
||||||
|
Exist A B =
|
||||||
|
{s = ["there exists"] ++ indef ++ A.s ! sg ++ B.$0 ++ ["such that"] ++ B.s} ;
|
||||||
|
Abs = {s = ["we have a contradiction"]} ;
|
||||||
|
Neg A = {s = ["it is not the case that"] ++ A.s} ;
|
||||||
|
ImplP A B = {s = "if" ++ A.s ++ "then" ++ B.s} ;
|
||||||
|
ConjI A B a b = {s = a.s ++ "." ++ b.s ++ [". Hence"] ++ A.s ++ "and" ++ B.s} ;
|
||||||
|
ConjEl A B c = {s = c.s ++ [". A fortiori ,"] ++ A.s} ;
|
||||||
|
ConjEr A B c = {s = c.s ++ [". A fortiori ,"] ++ B.s} ;
|
||||||
|
DisjIl A B a = {s = a.s ++ [". A fortiori ,"] ++ A.s ++ "or" ++ B.s} ;
|
||||||
|
DisjIr A B b = {s = b.s ++ [". A fortiori ,"] ++ A.s ++ "or" ++ B.s} ;
|
||||||
|
DisjE A B C c d e = {s =
|
||||||
|
c.s ++
|
||||||
|
[". There are two possibilities . First , assume"] ++
|
||||||
|
A.s ++ "(" ++ d.$0 ++ ")" ++ "." ++ d.s ++
|
||||||
|
[". Second , assume"] ++ B.s ++ "(" ++ e.$0 ++ ")" ++ "." ++ e.s ++
|
||||||
|
[". Thus"] ++ C.s ++ ["in both cases"]} ;
|
||||||
|
ImplI A B b = {s =
|
||||||
|
"assume" ++ A.s ++ "(" ++ b.$0 ++ ")" ++ "." ++
|
||||||
|
b.s ++ [". Hence , if"] ++ A.s ++ "then" ++ B.s} ;
|
||||||
|
ImplE A B c a = {s = a.s ++ [". But"] ++ c.s ++ [". Hence"] ++ B.s} ;
|
||||||
|
NegI A b = {s =
|
||||||
|
"assume" ++ A.s ++ "(" ++ b.$0 ++ ")" ++ "." ++ b.s ++
|
||||||
|
[". Hence, it is not the case that"] ++ A.s} ;
|
||||||
|
NegE A c a =
|
||||||
|
{s = a.s ++ [". But"] ++ c.s ++ [". We have a contradiction"]} ;
|
||||||
|
UnivI A B b = {s =
|
||||||
|
["consider an arbitrary"] ++ A.s ! sg ++ b.$0 ++ "." ++ b.s ++
|
||||||
|
[". Hence, for all"] ++ A.s ! pl ++ B.$0 ++ "," ++ B.s} ;
|
||||||
|
UnivE A B c a =
|
||||||
|
{s = c.s ++ [". Hence"] ++ B.s ++ "for" ++ B.$0 ++ ["set to"] ++ a.s} ;
|
||||||
|
ExistI A B a b = {s =
|
||||||
|
b.s ++ [". Hence, there exists"] ++ indef ++
|
||||||
|
A.s ! sg ++ B.$0 ++ ["such that"] ++ B.s} ;
|
||||||
|
ExistE A B C c d = {s =
|
||||||
|
c.s ++ [". Consider an arbitrary"] ++ d.$0 ++
|
||||||
|
["and assume that"] ++ B.s ++ "(" ++ d.$1 ++ ")" ++ "." ++ d.s ++
|
||||||
|
[". Hence"] ++ C.s ++ ["independently of"] ++ d.$0} ;
|
||||||
|
AbsE C c = {s = c.s ++ [". We may conclude"] ++ C.s} ;
|
||||||
|
Hypo A a = {s = ["by the hypothesis"] ++ a.s ++ "," ++ A.s} ;
|
||||||
|
Pron _ _ = {s = "it"} ;
|
||||||
|
|
||||||
|
} ;
|
||||||
27
grammars/logic/LogicResEng.gf
Normal file
27
grammars/logic/LogicResEng.gf
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
resource LogicResEng = {
|
||||||
|
|
||||||
|
param Num = sg | pl ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
|
||||||
|
ss : Str -> {s : Str} = \s -> {s = s} ;
|
||||||
|
|
||||||
|
nomReg : Str -> Num => Str = \s -> table {sg => s ; pl => s + "s"} ;
|
||||||
|
|
||||||
|
indef : Str = pre {"a" ; "an" / strs {"a" ; "e" ; "i" ; "o"}} ;
|
||||||
|
|
||||||
|
LinElem : Type = {s : Str} ;
|
||||||
|
LinProp : Type = {s : Str} ;
|
||||||
|
|
||||||
|
adj1 : Str -> LinElem -> LinProp =
|
||||||
|
\adj,x -> ss (x.s ++ "is" ++ adj) ;
|
||||||
|
adj2 : Str -> LinElem -> LinElem -> LinProp =
|
||||||
|
\adj,x,y -> ss (x.s ++ "is" ++ adj ++ y.s) ;
|
||||||
|
|
||||||
|
fun1 : Str -> LinElem -> LinElem =
|
||||||
|
\f,x -> ss ("the" ++ f ++ "of" ++ x.s) ;
|
||||||
|
fun2 : Str -> LinElem -> LinElem -> LinElem =
|
||||||
|
\f,x,y -> ss ("the" ++ f ++ "of" ++ x.s ++ "and" ++ y.s) ;
|
||||||
|
|
||||||
|
|
||||||
|
} ;
|
||||||
105
grammars/prelude/Coordination.gf
Normal file
105
grammars/prelude/Coordination.gf
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
resource Coordination = {
|
||||||
|
|
||||||
|
param
|
||||||
|
ListSize = TwoElem | ManyElem ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
SS = {s : Str} ; ----
|
||||||
|
|
||||||
|
ListX = {s1,s2 : Str} ;
|
||||||
|
|
||||||
|
twoStr : (x,y : Str) -> ListX = \x,y ->
|
||||||
|
{s1 = x ; s2 = y} ;
|
||||||
|
consStr : Str -> ListX -> Str -> ListX = \comma,xs,x ->
|
||||||
|
{s1 = xs.s1 ++ comma ++ xs.s2 ; s2 = x } ;
|
||||||
|
|
||||||
|
twoSS : (_,_ : SS) -> ListX = \x,y ->
|
||||||
|
twoStr x.s y.s ;
|
||||||
|
consSS : Str -> ListX -> SS -> ListX = \comma,xs,x ->
|
||||||
|
consStr comma xs x.s ;
|
||||||
|
|
||||||
|
Conjunction : Type = SS ;
|
||||||
|
ConjunctionDistr : Type = {s1 : Str ; s2 : Str} ;
|
||||||
|
|
||||||
|
conjunctX : Conjunction -> ListX -> Str = \or,xs ->
|
||||||
|
xs.s1 ++ or.s ++ xs.s2 ;
|
||||||
|
|
||||||
|
conjunctDistrX : ConjunctionDistr -> ListX -> Str = \or,xs ->
|
||||||
|
or.s1 ++ xs.s1 ++ or.s2 ++ xs.s2 ;
|
||||||
|
|
||||||
|
-- all this lifted to tables
|
||||||
|
|
||||||
|
ListTable : Type -> Type = \P -> {s1,s2 : P => Str} ;
|
||||||
|
|
||||||
|
twoTable : (P : Type) -> (_,_ : {s : P => Str}) -> ListTable P = \_,x,y ->
|
||||||
|
{s1 = x.s ; s2 = y.s} ;
|
||||||
|
|
||||||
|
consTable : (P : Type) -> Str -> ListTable P -> {s : P => Str} -> ListTable P =
|
||||||
|
\P,c,xs,x ->
|
||||||
|
{s1 = table P {o => xs.s1 ! o ++ c ++ xs.s2 ! o} ; s2 = x.s} ;
|
||||||
|
|
||||||
|
conjunctTable : (P : Type) -> Conjunction -> ListTable P -> {s : P => Str} =
|
||||||
|
\P,or,xs ->
|
||||||
|
{s = table P {p => xs.s1 ! p ++ or.s ++ xs.s2 ! p}} ;
|
||||||
|
|
||||||
|
conjunctDistrTable :
|
||||||
|
(P : Type) -> ConjunctionDistr -> ListTable P -> {s : P => Str} = \P,or,xs ->
|
||||||
|
{s = table P {p => or.s1++ xs.s1 ! p ++ or.s2 ++ xs.s2 ! p}} ;
|
||||||
|
|
||||||
|
-- ... and to two- and three-argument tables: how clumsy! ---
|
||||||
|
|
||||||
|
ListTable2 : Type -> Type -> Type = \P,Q ->
|
||||||
|
{s1,s2 : P => Q => Str} ;
|
||||||
|
|
||||||
|
twoTable2 : (P,Q : Type) -> (_,_ : {s : P => Q => Str}) -> ListTable2 P Q =
|
||||||
|
\_,_,x,y ->
|
||||||
|
{s1 = x.s ; s2 = y.s} ;
|
||||||
|
|
||||||
|
consTable2 :
|
||||||
|
(P,Q : Type) -> Str -> ListTable2 P Q -> {s : P => Q => Str} -> ListTable2 P Q =
|
||||||
|
\P,Q,c,xs,x ->
|
||||||
|
{s1 = table P {p => table Q {q => xs.s1 ! p ! q ++ c ++ xs.s2 ! p! q}} ;
|
||||||
|
s2 = x.s
|
||||||
|
} ;
|
||||||
|
|
||||||
|
conjunctTable2 :
|
||||||
|
(P,Q : Type) -> Conjunction -> ListTable2 P Q -> {s : P => Q => Str} =
|
||||||
|
\P,Q,or,xs ->
|
||||||
|
{s = table P {p => table Q {q => xs.s1 ! p ! q ++ or.s ++ xs.s2 ! p ! q}}} ;
|
||||||
|
|
||||||
|
conjunctDistrTable2 :
|
||||||
|
(P,Q : Type) -> ConjunctionDistr -> ListTable2 P Q -> {s : P => Q => Str} =
|
||||||
|
\_,_,or,xs ->
|
||||||
|
{s =
|
||||||
|
table {p => table {q => or.s1++ xs.s1 ! p ! q ++ or.s2 ++ xs.s2 ! p ! q}}} ;
|
||||||
|
|
||||||
|
ListTable3 : Type -> Type -> Type -> Type = \P,Q,R ->
|
||||||
|
{s1,s2 : P => Q => R => Str} ;
|
||||||
|
|
||||||
|
twoTable3 : (P,Q,R : Type) -> (_,_ : {s : P => Q => R => Str}) ->
|
||||||
|
ListTable3 P Q R =
|
||||||
|
\_,_,_,x,y ->
|
||||||
|
{s1 = x.s ; s2 = y.s} ;
|
||||||
|
|
||||||
|
consTable3 :
|
||||||
|
(P,Q,R : Type) -> Str -> ListTable3 P Q R -> {s : P => Q => R => Str} ->
|
||||||
|
ListTable3 P Q R =
|
||||||
|
\P,Q,R,c,xs,x ->
|
||||||
|
{s1 = \\p,q,r => xs.s1 ! p ! q ! r ++ c ++ xs.s2 ! p ! q ! r ;
|
||||||
|
s2 = x.s
|
||||||
|
} ;
|
||||||
|
|
||||||
|
conjunctTable3 :
|
||||||
|
(P,Q,R : Type) -> Conjunction -> ListTable3 P Q R -> {s : P => Q => R => Str} =
|
||||||
|
\P,Q,R,or,xs ->
|
||||||
|
{s = \\p,q,r => xs.s1 ! p ! q ! r ++ or.s ++ xs.s2 ! p ! q ! r} ;
|
||||||
|
|
||||||
|
conjunctDistrTable3 :
|
||||||
|
(P,Q,R : Type) -> ConjunctionDistr -> ListTable3 P Q R ->
|
||||||
|
{s : P => Q => R => Str} =
|
||||||
|
\P,Q,R,or,xs ->
|
||||||
|
{s = \\p,q,r => or.s1++ xs.s1 ! p ! q ! r ++ or.s2 ++ xs.s2 ! p ! q ! r} ;
|
||||||
|
|
||||||
|
comma = "," ;
|
||||||
|
|
||||||
|
} ;
|
||||||
25
grammars/prelude/Predef.gf
Normal file
25
grammars/prelude/Predef.gf
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- predefined functions for concrete syntax, defined in AppPredefined.hs
|
||||||
|
|
||||||
|
resource Predef = {
|
||||||
|
|
||||||
|
-- this type is for internal use only
|
||||||
|
param PBool = PTrue | PFalse ;
|
||||||
|
|
||||||
|
-- these operations have their definitions in AppPredefined.hs
|
||||||
|
oper Int : Type = variants {} ; ----
|
||||||
|
|
||||||
|
oper length : Tok -> Int = variants {} ;
|
||||||
|
oper drop : Int -> Tok -> Tok = variants {} ;
|
||||||
|
oper take : Int -> Tok -> Tok = variants {} ;
|
||||||
|
oper tk : Int -> Tok -> Tok = variants {} ;
|
||||||
|
oper dp : Int -> Tok -> Tok = variants {} ;
|
||||||
|
oper eqInt : Int -> Int -> PBool = variants {} ;
|
||||||
|
oper plus : Int -> Int -> Int = variants {} ;
|
||||||
|
|
||||||
|
oper eqStr : Tok -> Tok -> PBool = variants {} ;
|
||||||
|
oper eqTok : (P : Type) -> P -> P -> PBool = variants {} ;
|
||||||
|
oper show : (P : Type) -> P -> Tok = variants {} ;
|
||||||
|
oper read : (P : Type) -> Tok -> P = variants {} ;
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
83
grammars/prelude/Prelude.gf
Normal file
83
grammars/prelude/Prelude.gf
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
-- language-independent prelude facilities
|
||||||
|
|
||||||
|
resource Prelude = open (Predef = Predef) in {
|
||||||
|
|
||||||
|
oper
|
||||||
|
-- to construct records and tables
|
||||||
|
SS : Type = {s : Str} ;
|
||||||
|
ss : Str -> SS = \s -> {s = s} ;
|
||||||
|
ss2 : (_,_ : Str) -> SS = \x,y -> ss (x ++ y) ;
|
||||||
|
ss3 : (_,_ ,_: Str) -> SS = \x,y,z -> ss (x ++ y ++ z) ;
|
||||||
|
|
||||||
|
cc2 : (_,_ : SS) -> SS = \x,y -> ss (x.s ++ y.s) ;
|
||||||
|
|
||||||
|
SS1 : Type -> Type = \P -> {s : P => Str} ;
|
||||||
|
ss1 : (A : Type) -> Str -> SS1 A = \A,s -> {s = table {_ => s}} ;
|
||||||
|
|
||||||
|
SP1 : Type -> Type = \P -> {s : Str ; p : P} ;
|
||||||
|
sp1 : (A : Type) -> Str -> A -> SP1 A = \_,s,a -> {s = s ; p = a} ;
|
||||||
|
|
||||||
|
nonExist : Str = variants {} ;
|
||||||
|
|
||||||
|
optStr : Str -> Str = \s -> variants {s ; []} ;
|
||||||
|
|
||||||
|
constTable : (A,B : Type) -> B -> A => B = \_,_,b -> \\_ => b ;
|
||||||
|
constStr : (A : Type) -> Str -> A => Str = \A -> constTable A Str ;
|
||||||
|
|
||||||
|
infixSS : Str -> SS -> SS -> SS = \f,x,y -> ss (x.s ++ f ++ y.s) ;
|
||||||
|
prefixSS : Str -> SS -> SS = \f,x -> ss (f ++ x.s) ;
|
||||||
|
postfixSS : Str -> SS -> SS = \f,x -> ss (x.s ++ f) ;
|
||||||
|
embedSS : Str -> Str -> SS -> SS = \f,g,x -> ss (f ++ x.s ++ g) ;
|
||||||
|
|
||||||
|
-- discontinuous
|
||||||
|
SD2 = {s1,s2 : Str} ;
|
||||||
|
sd2 : (_,_ : Str) -> SD2 = \x,y -> {s1 = x ; s2 = y} ;
|
||||||
|
|
||||||
|
-- parentheses
|
||||||
|
paren : Str -> Str = \s -> "(" ++ s ++ ")" ;
|
||||||
|
parenss : SS -> SS = \s -> ss (paren s.s) ;
|
||||||
|
|
||||||
|
-- free order between two strings
|
||||||
|
bothWays : Str -> Str -> Str = \x,y -> variants {x ++ y ; y ++ x} ;
|
||||||
|
|
||||||
|
-- parametric order between two strings
|
||||||
|
preOrPost : Bool -> Str -> Str -> Str = \pr,x,y ->
|
||||||
|
if_then_else Str pr (x ++ y) (y ++ x) ;
|
||||||
|
|
||||||
|
-- Booleans
|
||||||
|
|
||||||
|
param Bool = True | False ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
if_then_else : (A : Type) -> Bool -> A -> A -> A = \_,c,d,e ->
|
||||||
|
case c of {
|
||||||
|
True => d ; ---- should not need to qualify
|
||||||
|
False => e
|
||||||
|
} ;
|
||||||
|
|
||||||
|
andB : (_,_ : Bool) -> Bool = \a,b -> if_then_else Bool a b False ;
|
||||||
|
orB : (_,_ : Bool) -> Bool = \a,b -> if_then_else Bool a True b ;
|
||||||
|
notB : Bool -> Bool = \a -> if_then_else Bool a False True ;
|
||||||
|
|
||||||
|
|
||||||
|
-- zero, one, two, or more (elements in a list etc)
|
||||||
|
|
||||||
|
param
|
||||||
|
ENumber = E0 | E1 | E2 | Emore ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
eNext : ENumber -> ENumber = \e -> case e of {
|
||||||
|
E0 => E1 ; E1 => E2 ; _ => Emore} ;
|
||||||
|
|
||||||
|
-- these were defined in Predef before
|
||||||
|
oper isNil : Tok -> Bool = \b -> pbool2bool (Predef.eqStr [] b) ;
|
||||||
|
|
||||||
|
oper ifTok : (A : Type) -> Tok -> Tok -> A -> A -> A = \A,t,u,a,b ->
|
||||||
|
case Predef.eqStr t u of {Predef.PTrue => a ; Predef.PFalse => b} ;
|
||||||
|
|
||||||
|
-- so we need an interface
|
||||||
|
oper pbool2bool : Predef.PBool -> Bool = \b -> case b of {
|
||||||
|
Predef.PFalse => False ; Predef.PTrue => True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
} ;
|
||||||
36
grammars/resource/abstract/Database.gf
Normal file
36
grammars/resource/abstract/Database.gf
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
abstract Database = {
|
||||||
|
|
||||||
|
flags startcat=Query ;
|
||||||
|
|
||||||
|
cat
|
||||||
|
Query ; Phras ; Statement ; Question ;
|
||||||
|
Noun ; Subject ; Value ; Property ; Relation ; Comparison ; Name ;
|
||||||
|
Feature ;
|
||||||
|
|
||||||
|
fun
|
||||||
|
LongForm : Phras -> Query ;
|
||||||
|
ShortForm : Phras -> Query ;
|
||||||
|
|
||||||
|
WhichAre : Noun -> Property -> Phras ;
|
||||||
|
IsThere : Noun -> Phras ;
|
||||||
|
AreThere : Noun -> Phras ;
|
||||||
|
IsIt : Subject -> Property -> Phras ;
|
||||||
|
WhatIs : Value -> Phras ;
|
||||||
|
|
||||||
|
MoreThan : Comparison -> Subject -> Property ;
|
||||||
|
TheMost : Comparison -> Noun -> Value ;
|
||||||
|
Relatively : Comparison -> Noun -> Property ;
|
||||||
|
|
||||||
|
RelatedTo : Relation -> Subject -> Property ;
|
||||||
|
|
||||||
|
Individual : Name -> Subject ;
|
||||||
|
AllN : Noun -> Subject ;
|
||||||
|
Any : Noun -> Subject ;
|
||||||
|
MostN : Noun -> Subject ;
|
||||||
|
EveryN : Noun -> Subject ;
|
||||||
|
|
||||||
|
FeatureOf : Feature -> Subject -> Subject ;
|
||||||
|
ValueOf : Feature -> Name -> Value ;
|
||||||
|
|
||||||
|
WithProperty : Noun -> Property -> Noun ;
|
||||||
|
} ;
|
||||||
4
grammars/resource/abstract/PredefAbs.gf
Normal file
4
grammars/resource/abstract/PredefAbs.gf
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
abstract PredefAbs = {
|
||||||
|
cat String ; Int ;
|
||||||
|
} ;
|
||||||
|
|
||||||
266
grammars/resource/abstract/ResAbs.gf
Normal file
266
grammars/resource/abstract/ResAbs.gf
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
--1 Abstract Syntax for Multilingual Resource Grammar
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002 -- 2003
|
||||||
|
--
|
||||||
|
-- Although concrete syntax differs a lot between different languages,
|
||||||
|
-- many structures can be found that are common, on a certain level
|
||||||
|
-- of abstraction. What we will present in the following is an abstract
|
||||||
|
-- syntax that has been successfully defined for English, French, German,
|
||||||
|
-- Italian, Russian, and Swedish. It has been applied to define language
|
||||||
|
-- fragments on technical or near-to-technical domains: database queries,
|
||||||
|
-- video recorder dialogue systems, software specifications, and a
|
||||||
|
-- health-related phrase book.
|
||||||
|
--
|
||||||
|
-- To use the resource in applications, you need the following
|
||||||
|
-- $cat$ and $fun$ rules in $oper$ form, completed by taking the
|
||||||
|
-- $lincat$ and $lin$ judgements of a particular language. There is
|
||||||
|
-- a GF command for making this translation automatically.
|
||||||
|
|
||||||
|
--2 Categories
|
||||||
|
--
|
||||||
|
-- The categories of this resource grammar are mostly 'standard' categories
|
||||||
|
-- of linguistics. Their is no claim that they correspond to semantic categories
|
||||||
|
-- definable in type theory: to define such correspondences it the business
|
||||||
|
-- of applications grammars.
|
||||||
|
--
|
||||||
|
-- Categories that may look special are $Adj2$, $Fun$, and $TV$. They are all
|
||||||
|
-- instances of endowing another category with a complement, which can be either
|
||||||
|
-- a direct object (whose case may vary) or a prepositional phrase. This, together
|
||||||
|
-- with the category $Adv$, removes the need of a category of
|
||||||
|
-- 'prepositional phrases', which is too language-dependent to make sense
|
||||||
|
-- on this level of abstraction.
|
||||||
|
--
|
||||||
|
|
||||||
|
abstract ResAbs = {
|
||||||
|
|
||||||
|
--3 Nouns and noun phrases
|
||||||
|
--
|
||||||
|
|
||||||
|
cat
|
||||||
|
N ; -- simple common noun, e.g. "car"
|
||||||
|
CN ; -- common noun phrase, e.g. "red car", "car that John owns"
|
||||||
|
NP ; -- noun phrase, e.g. "John", "all cars", "you"
|
||||||
|
PN ; -- proper name, e.g. "John", "New York"
|
||||||
|
Det ; -- determiner, e.g. "every", "all"
|
||||||
|
Fun ; -- function word, e.g. "mother (of)"
|
||||||
|
Fun2 ; -- two-place function, e.g. "flight (from) (to)"
|
||||||
|
|
||||||
|
--3 Adjectives and adjectival phrases
|
||||||
|
--
|
||||||
|
|
||||||
|
Adj1 ; -- one-place adjective, e.g. "even"
|
||||||
|
Adj2 ; -- two-place adjective, e.g. "divisible (by)"
|
||||||
|
AdjDeg ; -- degree adjective, e.g. "big/bigger/biggest"
|
||||||
|
AP ; -- adjective phrase, e.g. "divisible by two", "bigger than John"
|
||||||
|
|
||||||
|
--3 Verbs and verb phrases
|
||||||
|
--
|
||||||
|
|
||||||
|
V ; -- one-place verb, e.g. "walk"
|
||||||
|
TV ; -- two-place verb, e.g. "love", "wait (for)", "switch on"
|
||||||
|
VS ; -- sentence-compl. verb e.g. "say", "prove"
|
||||||
|
VP ; -- verb phrase, e.g. "switch the light on"
|
||||||
|
|
||||||
|
--3 Adverbials
|
||||||
|
--
|
||||||
|
|
||||||
|
AdV ; -- adverbial e.g. "now", "in the house"
|
||||||
|
AdA ; -- ad-adjective e.g. "very"
|
||||||
|
AdS ; -- sentence adverbial e.g. "therefore", "otherwise"
|
||||||
|
|
||||||
|
--3 Sentences and relative clauses
|
||||||
|
--
|
||||||
|
|
||||||
|
S ; -- sentence, e.g. "John walks"
|
||||||
|
Slash ; -- sentence without NP, e.g. "John waits for (...)"
|
||||||
|
RP ; -- relative pronoun, e.g. "which", "the mother of whom"
|
||||||
|
RC ; -- relative clause, e.g. "who walks", "that I wait for"
|
||||||
|
|
||||||
|
--3 Questions and imperatives
|
||||||
|
--
|
||||||
|
|
||||||
|
IP ; -- interrogative pronoun, e.g. "who", "whose mother", "which yellow car"
|
||||||
|
IAdv ; -- interrogative adverb., e.g. "when", "why"
|
||||||
|
Qu ; -- question, e.g. "who walks"
|
||||||
|
Imp ; -- imperative, e.g. "walk!"
|
||||||
|
|
||||||
|
--3 Coordination and subordination
|
||||||
|
--
|
||||||
|
|
||||||
|
Conj ; -- conjunction, e.g. "and"
|
||||||
|
ConjD ; -- distributed conj. e.g. "both - and"
|
||||||
|
Subj ; -- subjunction, e.g. "if", "when"
|
||||||
|
|
||||||
|
ListS ; -- list of sentences
|
||||||
|
ListAP ; -- list of adjectival phrases
|
||||||
|
ListNP ; -- list of noun phrases
|
||||||
|
|
||||||
|
--3 Complete utterances
|
||||||
|
--
|
||||||
|
|
||||||
|
Phr ; -- full phrase, e.g. "John walks.","Who walks?", "Wait for me!"
|
||||||
|
Text ; -- sequence of phrases e.g. "One is odd. Therefore, two is even."
|
||||||
|
|
||||||
|
--2 Rules
|
||||||
|
--
|
||||||
|
-- This set of rules is minimal, in the sense defining the simplest combinations
|
||||||
|
-- of categories and of not having redundant rules.
|
||||||
|
-- When the resource grammar is used as a library, it will often be useful to
|
||||||
|
-- access it through an intermediate library that defines more rules as
|
||||||
|
-- combinations of the ones below.
|
||||||
|
|
||||||
|
--3 Nouns and noun phrases
|
||||||
|
--
|
||||||
|
|
||||||
|
fun
|
||||||
|
UseN : N -> CN ; -- "car"
|
||||||
|
ModAdj : AP -> CN -> CN ; -- "red car"
|
||||||
|
DetNP : Det -> CN -> NP ; -- "every car"
|
||||||
|
IndefOneNP, IndefManyNP : CN -> NP ; -- "a car", "cars"
|
||||||
|
DefOneNP, DefManyNP : CN -> NP ; -- "the car", "the cars"
|
||||||
|
ModGenOne, ModGenMany : NP -> CN -> NP ; -- "John's car", "John's cars"
|
||||||
|
UsePN : PN -> NP ; -- "John"
|
||||||
|
UseFun : Fun -> CN ; -- "successor"
|
||||||
|
AppFun : Fun -> NP -> CN ; -- "successor of zero"
|
||||||
|
AppFun2 : Fun2 -> NP -> Fun ; -- "flight from Paris"
|
||||||
|
CNthatS : CN -> S -> CN ; -- "idea that the Earth is flat"
|
||||||
|
|
||||||
|
--3 Adjectives and adjectival phrases
|
||||||
|
--
|
||||||
|
|
||||||
|
AdjP1 : Adj1 -> AP ; -- "red"
|
||||||
|
ComplAdj : Adj2 -> NP -> AP ; -- "divisible by two"
|
||||||
|
PositAdjP : AdjDeg -> AP ; -- "old"
|
||||||
|
ComparAdjP : AdjDeg -> NP -> AP ; -- "older than John"
|
||||||
|
SuperlNP : AdjDeg -> CN -> NP ; -- "the oldest man"
|
||||||
|
|
||||||
|
--3 Verbs and verb phrases
|
||||||
|
--
|
||||||
|
|
||||||
|
PosV, NegV : V -> VP ; -- "walk", "doesn't walk"
|
||||||
|
PosA, NegA : AP -> VP ; -- "is old", "isn't old"
|
||||||
|
PosCN, NegCN : CN -> VP ; -- "is a man", "isn't a man"
|
||||||
|
PosTV, NegTV : TV -> NP -> VP ; -- "sees John", "doesn't see John"
|
||||||
|
PosPassV, NegPassV : V -> VP ; -- "is seen", "is not seen"
|
||||||
|
PosNP, NegNP : NP -> VP ; -- "is John", "is not John"
|
||||||
|
PosVS, NegVS : VS -> S -> VP ; -- "says that I run", "doesn't say..."
|
||||||
|
|
||||||
|
--3 Adverbials
|
||||||
|
--
|
||||||
|
|
||||||
|
AdvVP : VP -> AdV -> VP ; -- "always walks", "walks in the park"
|
||||||
|
LocNP : NP -> AdV ; -- "in London"
|
||||||
|
AdvCN : CN -> AdV -> CN ; -- "house in London", "house today"
|
||||||
|
|
||||||
|
AdvAP : AdA -> AP -> AP ; -- "very good"
|
||||||
|
|
||||||
|
|
||||||
|
--3 Sentences and relative clauses
|
||||||
|
--
|
||||||
|
|
||||||
|
PredVP : NP -> VP -> S ; -- "John walks"
|
||||||
|
PosSlashTV, NegSlashTV : NP -> TV -> Slash ; -- "John sees", "John doesn's see"
|
||||||
|
OneVP : VP -> S ; -- "one walks"
|
||||||
|
|
||||||
|
IdRP : RP ; -- "which"
|
||||||
|
FunRP : Fun -> RP -> RP ; -- "the successor of which"
|
||||||
|
RelVP : RP -> VP -> RC ; -- "who walks"
|
||||||
|
RelSlash : RP -> Slash -> RC ; -- "that I wait for"/"for which I wait"
|
||||||
|
ModRC : CN -> RC -> CN ; -- "man who walks"
|
||||||
|
RelSuch : S -> RC ; -- "such that it is even"
|
||||||
|
|
||||||
|
--3 Questions and imperatives
|
||||||
|
--
|
||||||
|
|
||||||
|
WhoOne, WhoMany : IP ; -- "who (is)", "who (are)"
|
||||||
|
WhatOne, WhatMany : IP ; -- "what (is)", "what (are)"
|
||||||
|
FunIP : Fun -> IP -> IP ; -- "the mother of whom"
|
||||||
|
NounIPOne, NounIPMany : CN -> IP ; -- "which car", "which cars"
|
||||||
|
|
||||||
|
QuestVP : NP -> VP -> Qu ; -- "does John walk"
|
||||||
|
IntVP : IP -> VP -> Qu ; -- "who walks"
|
||||||
|
IntSlash : IP -> Slash -> Qu ; -- "whom does John see"
|
||||||
|
QuestAdv : IAdv -> NP -> VP -> Qu ; -- "why do you walk"
|
||||||
|
|
||||||
|
ImperVP : VP -> Imp ; -- "be a man"
|
||||||
|
|
||||||
|
IndicPhrase : S -> Phr ; -- "I walk."
|
||||||
|
QuestPhrase : Qu -> Phr ; -- "Do I walk?"
|
||||||
|
ImperOne, ImperMany : Imp -> Phr ; -- "Be a man!", "Be men!"
|
||||||
|
|
||||||
|
AdvS : AdS -> S -> Phr ; -- "Therefore, 2 is prime."
|
||||||
|
|
||||||
|
--3 Coordination
|
||||||
|
--
|
||||||
|
-- We consider "n"-ary coordination, with "n" > 1. To this end, we have introduced
|
||||||
|
-- a *list category* $ListX$ for each category $X$ whose expressions we want to
|
||||||
|
-- conjoin. Each list category has two constructors, the base case being $TwoX$.
|
||||||
|
|
||||||
|
-- We have not defined coordination of all possible categories here,
|
||||||
|
-- since it can be tricky in many languages. For instance, $VP$ coordination
|
||||||
|
-- is linguistically problematic in German because $VP$ is a discontinuous
|
||||||
|
-- category.
|
||||||
|
|
||||||
|
ConjS : Conj -> ListS -> S ; -- "John walks and Mary runs"
|
||||||
|
ConjAP : Conj -> ListAP -> AP ; -- "even and prime"
|
||||||
|
ConjNP : Conj -> ListNP -> NP ; -- "John or Mary"
|
||||||
|
|
||||||
|
ConjDS : ConjD -> ListS -> S ; -- "either John walks or Mary runs"
|
||||||
|
ConjDAP : ConjD -> ListAP -> AP ; -- "both even and prime"
|
||||||
|
ConjDNP : ConjD -> ListNP -> NP ; -- "either John or Mary"
|
||||||
|
|
||||||
|
TwoS : S -> S -> ListS ;
|
||||||
|
ConsS : ListS -> S -> ListS ;
|
||||||
|
|
||||||
|
TwoAP : AP -> AP -> ListAP ;
|
||||||
|
ConsAP : ListAP -> AP -> ListAP ;
|
||||||
|
|
||||||
|
TwoNP : NP -> NP -> ListNP ;
|
||||||
|
ConsNP : ListNP -> NP -> ListNP ;
|
||||||
|
|
||||||
|
--3 Subordination
|
||||||
|
--
|
||||||
|
-- Subjunctions are different from conjunctions, but form
|
||||||
|
-- a uniform category among themselves.
|
||||||
|
|
||||||
|
SubjS : Subj -> S -> S -> S ; -- "if 2 is odd, 3 is even"
|
||||||
|
SubjImper : Subj -> S -> Imp -> Imp ; -- "if it is hot, use a glove!"
|
||||||
|
SubjQu : Subj -> S -> Qu -> Qu ; -- "if you are new, who are you?"
|
||||||
|
|
||||||
|
--2 One-word utterances
|
||||||
|
--
|
||||||
|
-- These are, more generally, *one-phrase utterances*. The list below
|
||||||
|
-- is very incomplete.
|
||||||
|
|
||||||
|
PhrNP : NP -> Phr ; -- "Some man.", "John."
|
||||||
|
PhrOneCN, PhrManyCN : CN -> Phr ; -- "A car.", "Cars."
|
||||||
|
PhrIP : IAdv -> Phr ; -- "Who?"
|
||||||
|
PhrIAdv : IAdv -> Phr ; -- "Why?"
|
||||||
|
|
||||||
|
--2 Text formation
|
||||||
|
--
|
||||||
|
-- A text is a sequence of phrases. It is defined like a non-empty list.
|
||||||
|
|
||||||
|
OnePhr : Phr -> Text ;
|
||||||
|
ConsPhr : Phr -> Text -> Text ;
|
||||||
|
|
||||||
|
--2 Examples of structural words
|
||||||
|
--
|
||||||
|
-- Here we have some words belonging to closed classes and appearing
|
||||||
|
-- in all languages we have considered.
|
||||||
|
-- Sometimes they are not really meaningful, e.g. $TheyNP$ in French
|
||||||
|
-- should really be replaced by masculine and feminine variants.
|
||||||
|
|
||||||
|
EveryDet, AllDet, WhichDet, MostDet : Det ; -- every, all, which, most
|
||||||
|
INP, ThouNP, HeNP, SheNP, ItNP : NP ; -- personal pronouns in singular
|
||||||
|
WeNP, YeNP, TheyNP : NP ; -- personal pronouns in plural
|
||||||
|
YouNP : NP ; -- the polite you
|
||||||
|
WhenIAdv,WhereIAdv,WhyIAdv,HowIAdv : IAdv ; -- when, where, why, how
|
||||||
|
AndConj, OrConj : Conj ; -- and, or
|
||||||
|
BothAnd, EitherOr, NeitherNor : ConjD ; -- both-and, either-or, neither-nor
|
||||||
|
IfSubj, WhenSubj : Subj ; -- if, when
|
||||||
|
PhrYes, PhrNo : Phr ; -- yes, no
|
||||||
|
VeryAdv, TooAdv : AdA ; -- very, too
|
||||||
|
OtherwiseAdv, ThereforeAdv : AdS ; -- therefore, otherwise
|
||||||
|
} ;
|
||||||
|
|
||||||
15
grammars/resource/abstract/Restaurant.gf
Normal file
15
grammars/resource/abstract/Restaurant.gf
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
abstract Restaurant = Database ** {
|
||||||
|
|
||||||
|
fun
|
||||||
|
Restaurant, Bar : Noun ;
|
||||||
|
French, Italian, Indian, Japanese : Property ;
|
||||||
|
address, phone, priceLevel : Feature ;
|
||||||
|
Cheap, Expensive : Comparison ;
|
||||||
|
|
||||||
|
WhoRecommend : Name -> Phras ;
|
||||||
|
WhoHellRecommend : Name -> Phras ;
|
||||||
|
|
||||||
|
|
||||||
|
-- examples of restaurant names
|
||||||
|
LucasCarton : Name ;
|
||||||
|
} ;
|
||||||
15
grammars/resource/abstract/TestAbs.gf
Normal file
15
grammars/resource/abstract/TestAbs.gf
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
abstract TestAbs = ResAbs ** {
|
||||||
|
|
||||||
|
-- a random sample of lexicon to test resource grammar with
|
||||||
|
|
||||||
|
fun
|
||||||
|
Big, Small, Old, Young : AdjDeg ;
|
||||||
|
Man, Woman, Car, House, Light : N ;
|
||||||
|
Walk, Run : V ;
|
||||||
|
Send, Wait, Love, SwitchOn, SwitchOff : TV ;
|
||||||
|
Say, Prove : VS ;
|
||||||
|
Mother, Uncle : Fun ;
|
||||||
|
Connection : Fun2 ;
|
||||||
|
Well, Always : AdV ;
|
||||||
|
John, Mary : PN ;
|
||||||
|
} ;
|
||||||
51
grammars/resource/english/DatabaseEng.gf
Normal file
51
grammars/resource/english/DatabaseEng.gf
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
concrete DatabaseEng of Database = open Prelude,Syntax,English,Predication,Paradigms,DatabaseRes in {
|
||||||
|
|
||||||
|
flags lexer=text ; unlexer=text ;
|
||||||
|
|
||||||
|
lincat
|
||||||
|
Phras = SS1 Bool ; -- long or short form
|
||||||
|
Subject = NP ;
|
||||||
|
Noun = CN ;
|
||||||
|
Property = AP ;
|
||||||
|
Comparison = AdjDeg ;
|
||||||
|
Relation = Adj2 ;
|
||||||
|
Feature = Fun ;
|
||||||
|
Value = NP ;
|
||||||
|
Name = ProperName ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
LongForm sent = ss (sent.s ! True ++ "?") ;
|
||||||
|
ShortForm sent = ss (sent.s ! False ++ "?") ;
|
||||||
|
|
||||||
|
WhichAre A B = mkSent (defaultQuestion (IntVP (NounIPMany A) (PosA B)))
|
||||||
|
(defaultNounPhrase (IndefManyNP (ModAdj B A))) ;
|
||||||
|
|
||||||
|
IsIt Q A = mkSentSame (defaultQuestion (QuestVP Q (PosA A))) ;
|
||||||
|
|
||||||
|
MoreThan = ComparAdjP ;
|
||||||
|
TheMost = SuperlNP ;
|
||||||
|
Relatively C _ = PositAdjP C ;
|
||||||
|
|
||||||
|
RelatedTo = ComplAdj ;
|
||||||
|
|
||||||
|
FeatureOf = appFun1 ;
|
||||||
|
ValueOf F V = appFun1 F (UsePN V) ;
|
||||||
|
|
||||||
|
WithProperty A B = ModAdj B A ;
|
||||||
|
|
||||||
|
Individual = UsePN ;
|
||||||
|
|
||||||
|
AllN = DetNP AllDet ;
|
||||||
|
MostN = DetNP MostDet ;
|
||||||
|
EveryN = DetNP EveryDet ;
|
||||||
|
|
||||||
|
-- only these are language-dependent
|
||||||
|
|
||||||
|
Any = detNounPhrase anyPlDet ; ---
|
||||||
|
|
||||||
|
IsThere A = mkSentPrel ["is there"] (defaultNounPhrase (IndefOneNP A)) ;
|
||||||
|
AreThere A = mkSentPrel ["are there"] (defaultNounPhrase (IndefManyNP A)) ;
|
||||||
|
|
||||||
|
WhatIs V = mkSentPrel ["what is"] (defaultNounPhrase V) ;
|
||||||
|
|
||||||
|
} ;
|
||||||
11
grammars/resource/english/DatabaseEngRes.gf
Normal file
11
grammars/resource/english/DatabaseEngRes.gf
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
resource DatabaseEngRes = open Prelude in {
|
||||||
|
oper
|
||||||
|
mkSent : SS -> SS -> SS1 Bool = \long, short ->
|
||||||
|
{s = table {b => if_then_else Str b long.s short.s}} ;
|
||||||
|
|
||||||
|
mkSentPrel : Str -> SS -> SS1 Bool = \prel, matter ->
|
||||||
|
mkSent (ss (prel ++ matter.s)) matter ;
|
||||||
|
|
||||||
|
mkSentSame : SS -> SS1 Bool = \s ->
|
||||||
|
mkSent s s ;
|
||||||
|
} ;
|
||||||
1
grammars/resource/english/English.gf
Normal file
1
grammars/resource/english/English.gf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resource English = reuse ResEng ;
|
||||||
150
grammars/resource/english/Morpho.gf
Normal file
150
grammars/resource/english/Morpho.gf
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
--1 A Simple English Resource Morphology
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002
|
||||||
|
--
|
||||||
|
-- This resource morphology contains definitions needed in the resource
|
||||||
|
-- syntax. It moreover contains the most usual inflectional patterns.
|
||||||
|
--
|
||||||
|
-- We use the parameter types and word classes defined in $types.Eng.gf$.
|
||||||
|
|
||||||
|
resource Morpho = Types ** open Prelude in {
|
||||||
|
|
||||||
|
--2 Nouns
|
||||||
|
--
|
||||||
|
-- For conciseness and abstraction, we define a worst-case macro for
|
||||||
|
-- noun inflection. It is used for defining special case that
|
||||||
|
-- only need one string as argument.
|
||||||
|
|
||||||
|
oper
|
||||||
|
mkNoun : (_,_,_,_ : Str) -> CommonNoun =
|
||||||
|
\man,men, mans, mens -> {s = table {
|
||||||
|
Sg => table {Nom => man ; Gen => mans} ;
|
||||||
|
Pl => table {Nom => men ; Gen => mens}
|
||||||
|
}} ;
|
||||||
|
|
||||||
|
nounReg : Str -> CommonNoun = \dog ->
|
||||||
|
mkNoun dog (dog + "s") (dog + "'s") (dog + "s'");
|
||||||
|
|
||||||
|
nounS : Str -> CommonNoun = \kiss ->
|
||||||
|
mkNoun kiss (kiss + "es") (kiss + "'s") (kiss + "es'") ;
|
||||||
|
|
||||||
|
nounY : Str -> CommonNoun = \fl ->
|
||||||
|
mkNoun (fl + "y") (fl + "ies") (fl + "y's") (fl + "ies'") ;
|
||||||
|
|
||||||
|
--3 Proper names
|
||||||
|
--
|
||||||
|
-- Regular proper names are inflected with "'s" in the genitive.
|
||||||
|
|
||||||
|
nameReg : Str -> ProperName = \john ->
|
||||||
|
{s = table {Nom => john ; Gen => john + "'s"}} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Pronouns
|
||||||
|
--
|
||||||
|
-- Here we define personal and relative pronouns.
|
||||||
|
|
||||||
|
mkPronoun : (_,_,_,_ : Str) -> Number -> Person -> Pronoun = \I,me,my,mine,n,p ->
|
||||||
|
{s = table {NomP => I ; AccP => me ; GenP => my ; GenSP => mine} ;
|
||||||
|
n = n ; p = p} ;
|
||||||
|
|
||||||
|
pronI = mkPronoun "I" "me" "my" "mine" Sg P1 ;
|
||||||
|
pronYouSg = mkPronoun "you" "you" "your" "yours" Sg P2 ; -- verb form still OK
|
||||||
|
pronHe = mkPronoun "he" "him" "his" "his" Sg P3 ;
|
||||||
|
pronShe = mkPronoun "she" "her" "her" "hers" Sg P3 ;
|
||||||
|
|
||||||
|
pronWe = mkPronoun "we" "us" "our" "ours" Pl P1 ;
|
||||||
|
pronYouPl = mkPronoun "you" "you" "your" "yours" Pl P2 ;
|
||||||
|
pronThey = mkPronoun "they" "them" "their" "theirs" Pl P3 ;
|
||||||
|
|
||||||
|
-- Relative pronouns in the accusative have the 'no pronoun' variant.
|
||||||
|
-- The simple pronouns do not really depend on number.
|
||||||
|
|
||||||
|
relPron : RelPron = {s = table {
|
||||||
|
NoHum => \\_ => table {
|
||||||
|
NomP => variants {"that" ; "which"} ;
|
||||||
|
AccP => variants {"that" ; "which" ; []} ;
|
||||||
|
GenP => variants {"whose"} ;
|
||||||
|
GenSP => variants {"which"}
|
||||||
|
} ;
|
||||||
|
Hum => \\_ => table {
|
||||||
|
NomP => variants {"that" ; "who"} ;
|
||||||
|
AccP => variants {"that" ; "who" ; "whom" ; []} ;
|
||||||
|
GenP => variants {"whose"} ;
|
||||||
|
GenSP => variants {"whom"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Determiners
|
||||||
|
--
|
||||||
|
-- We have just a heuristic definition of the indefinite article.
|
||||||
|
-- There are lots of exceptions: consonantic "e" ("euphemism"), consonantic
|
||||||
|
-- "o" ("one-sided"), vocalic "u" ("umbrella").
|
||||||
|
|
||||||
|
artIndef = pre {"a" ;
|
||||||
|
"an" / strs {"a" ; "e" ; "i" ; "o" ; "A" ; "E" ; "I" ; "O" }} ;
|
||||||
|
|
||||||
|
artDef = "the" ;
|
||||||
|
|
||||||
|
--2 Adjectives
|
||||||
|
--
|
||||||
|
-- For the comparison of adjectives, three forms are needed in the worst case.
|
||||||
|
|
||||||
|
mkAdjDegr : (_,_,_ : Str) -> AdjDegr = \good,better,best ->
|
||||||
|
{s = table {Pos => good ; Comp => better ; Sup => best}} ;
|
||||||
|
|
||||||
|
adjDegrReg : Str -> AdjDegr = \long ->
|
||||||
|
mkAdjDegr long (long + "er") (long + "est") ;
|
||||||
|
|
||||||
|
adjDegrY : Str -> AdjDegr = \lovel ->
|
||||||
|
mkAdjDegr (lovel + "y") (lovel + "ier") (lovel + "iest") ;
|
||||||
|
|
||||||
|
-- Many adjectives are 'inflected' by adding a comparison word.
|
||||||
|
|
||||||
|
adjDegrLong : Str -> AdjDegr = \ridiculous ->
|
||||||
|
mkAdjDegr ridiculous ("more" ++ ridiculous) ("most" ++ ridiculous) ;
|
||||||
|
|
||||||
|
-- simple adjectives are just strings
|
||||||
|
|
||||||
|
simpleAdj : Str -> Adjective = ss ;
|
||||||
|
|
||||||
|
--3 Verbs
|
||||||
|
--
|
||||||
|
-- Except for "be", the worst case needs two forms.
|
||||||
|
|
||||||
|
mkVerbP3 : (_,_: Str) -> VerbP3 = \goes,go ->
|
||||||
|
{s = table {InfImp => go ; Indic P3 => goes ; Indic _ => go}} ;
|
||||||
|
|
||||||
|
regVerbP3 : Str -> VerbP3 = \walk ->
|
||||||
|
mkVerbP3 (walk + "s") walk ;
|
||||||
|
|
||||||
|
verbP3s : Str -> VerbP3 = \kiss ->
|
||||||
|
mkVerbP3 (kiss + "es") kiss ;
|
||||||
|
|
||||||
|
verbP3y : Str -> VerbP3 = \fl ->
|
||||||
|
mkVerbP3 (fl + "ies") (fl + "y") ;
|
||||||
|
|
||||||
|
verbP3Have = mkVerbP3 "has" "have" ;
|
||||||
|
|
||||||
|
verbP3Do = verbP3s "do" ;
|
||||||
|
|
||||||
|
verbBe : VerbP3 = {s = table {
|
||||||
|
InfImp => "be" ;
|
||||||
|
Indic P1 => "am" ;
|
||||||
|
Indic P2 => "are" ;
|
||||||
|
Indic P3 => "is"
|
||||||
|
}} ;
|
||||||
|
|
||||||
|
verbPart : VerbP3 -> Particle -> Verb = \v,p ->
|
||||||
|
v ** {s1 = p} ;
|
||||||
|
|
||||||
|
verbNoPart : VerbP3 -> Verb = \v -> verbPart v [] ;
|
||||||
|
|
||||||
|
-- The optional negation contraction is a useful macro e.g. for "do".
|
||||||
|
|
||||||
|
contractNot : Str -> Str = \is -> variants {is ++ "not" ; is + "n't"} ;
|
||||||
|
|
||||||
|
dont = contractNot (verbP3Do.s ! InfImp) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
229
grammars/resource/english/Paradigms.gf
Normal file
229
grammars/resource/english/Paradigms.gf
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
--1 English Lexical Paradigms
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2003
|
||||||
|
--
|
||||||
|
-- This is an API to the user of the resource grammar
|
||||||
|
-- for adding lexical items. It give shortcuts for forming
|
||||||
|
-- expressions of basic categories: nouns, adjectives, verbs.
|
||||||
|
--
|
||||||
|
-- Closed categories (determiners, pronouns, conjunctions) are
|
||||||
|
-- accessed through the resource syntax API, $resource.Abs.gf$.
|
||||||
|
--
|
||||||
|
-- The main difference with $morpho.Eng.gf$ is that the types
|
||||||
|
-- referred to are compiled resource grammar types. We have moreover
|
||||||
|
-- had the design principle of always having existing forms as string
|
||||||
|
-- arguments of the paradigms, not stems.
|
||||||
|
--
|
||||||
|
-- The following modules are presupposed:
|
||||||
|
|
||||||
|
resource Paradigms = open (Predef=Predef), Prelude, Syntax, English in {
|
||||||
|
|
||||||
|
--2 Parameters
|
||||||
|
--
|
||||||
|
-- To abstract over gender names, we define the following identifiers.
|
||||||
|
|
||||||
|
oper
|
||||||
|
human : Gender ;
|
||||||
|
nonhuman : Gender ;
|
||||||
|
|
||||||
|
-- To abstract over number names, we define the following.
|
||||||
|
|
||||||
|
singular : Number ;
|
||||||
|
plural : Number ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Nouns
|
||||||
|
|
||||||
|
-- Worst case: give all four forms and the semantic gender.
|
||||||
|
-- In practice the worst case is just: give singular and plural nominative.
|
||||||
|
|
||||||
|
oper
|
||||||
|
mkN : (man,men,man's,men's : Str) -> Gender -> N ;
|
||||||
|
nMan : (man,men : Str) -> Gender -> N ;
|
||||||
|
|
||||||
|
-- Regular nouns, nouns ending with "s", "y", or "o", and nouns with the same
|
||||||
|
-- plural form as the singular.
|
||||||
|
|
||||||
|
nReg : Str -> Gender -> N ; -- dog, dogs
|
||||||
|
nKiss : Str -> Gender -> N ; -- kiss, kisses
|
||||||
|
nFly : Str -> Gender -> N ; -- fly, flies
|
||||||
|
nHero : Str -> Gender -> N ; -- hero, heroes (= nKiss !)
|
||||||
|
nSheep : Str -> Gender -> N ; -- sheep, sheep
|
||||||
|
|
||||||
|
-- These use general heuristics, that recognizes the last letter. *N.B* it
|
||||||
|
-- does not get right with "boy", "rush", since it only looks at one letter.
|
||||||
|
|
||||||
|
nHuman : Str -> N ; -- gambler/actress/nanny
|
||||||
|
nNonhuman : Str -> N ; -- dog/kiss/fly
|
||||||
|
|
||||||
|
-- Nouns used as functions need a preposition. The most common is "of".
|
||||||
|
|
||||||
|
mkFun : N -> Preposition -> Fun ;
|
||||||
|
|
||||||
|
funHuman : Str -> Fun ; -- the father/mistress/daddy of
|
||||||
|
funNonhuman : Str -> Fun ; -- the successor/address/copy of
|
||||||
|
|
||||||
|
-- Proper names, with their regular genitive.
|
||||||
|
|
||||||
|
pnReg : (John : Str) -> PN ; -- John, John's
|
||||||
|
|
||||||
|
-- The most common cases on the top level havee shortcuts.
|
||||||
|
-- The regular "y"/"s" variation is taken into account in $CN$.
|
||||||
|
|
||||||
|
cnNonhuman : Str -> CN ;
|
||||||
|
cnHuman : Str -> CN ;
|
||||||
|
npReg : Str -> NP ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Adjectives
|
||||||
|
|
||||||
|
-- Non-comparison one-place adjectives just have one form.
|
||||||
|
|
||||||
|
mkAdj1 : (even : Str) -> Adj1 ;
|
||||||
|
|
||||||
|
-- Two-place adjectives need a preposition as second argument.
|
||||||
|
|
||||||
|
mkAdj2 : (divisible, by : Str) -> Adj2 ;
|
||||||
|
|
||||||
|
-- Comparison adjectives have three forms. The common irregular
|
||||||
|
-- cases are ones ending with "y" and a consonant that is duplicated.
|
||||||
|
|
||||||
|
mkAdjDeg : (good,better,best : Str) -> AdjDeg ;
|
||||||
|
|
||||||
|
aReg : (long : Str) -> AdjDeg ; -- long, longer, longest
|
||||||
|
aHappy : (happy : Str) -> AdjDeg ; -- happy, happier, happiest
|
||||||
|
aFat : (fat : Str) -> AdjDeg ; -- fat, fatter, fattest
|
||||||
|
aRidiculous : (ridiculous : Str) -> AdjDeg ; -- -/more/most ridiculous
|
||||||
|
|
||||||
|
-- On top level, there are adjectival phrases. The most common case is
|
||||||
|
-- just to use a one-place adjective.
|
||||||
|
|
||||||
|
apReg : Str -> AP ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Verbs
|
||||||
|
--
|
||||||
|
-- The fragment only has present tense so far, but in all persons.
|
||||||
|
-- Except for "be", the worst case needs two forms: the infinitive and
|
||||||
|
-- the third person singular.
|
||||||
|
|
||||||
|
mkV : (go, goes : Str) -> V ;
|
||||||
|
|
||||||
|
vReg : (walk : Str) -> V ; -- walk, walks
|
||||||
|
vKiss : (kiss : Str) -> V ; -- kiss, kisses
|
||||||
|
vFly : (fly : Str) -> V ; -- fly, flies
|
||||||
|
vGo : (go : Str) -> V ; -- go, goes (= vKiss !)
|
||||||
|
|
||||||
|
-- This generic function recognizes the special cases where the last
|
||||||
|
-- character is "y", "s", or "z". It is not right for "finish" and "convey".
|
||||||
|
|
||||||
|
vGen : Str -> V ; -- walk/kiss/fly
|
||||||
|
|
||||||
|
-- The verbs "be" and "have" are special.
|
||||||
|
|
||||||
|
vBe : V ;
|
||||||
|
vHave : V ;
|
||||||
|
|
||||||
|
-- Verbs with a particle.
|
||||||
|
|
||||||
|
vPart : (go, goes, up : Str) -> V ;
|
||||||
|
vPartReg : (get, up : Str) -> V ;
|
||||||
|
|
||||||
|
-- Two-place verbs, and the special case with direct object.
|
||||||
|
-- Notice that a particle can already be included in $V$.
|
||||||
|
|
||||||
|
mkTV : V -> Str -> TV ; -- look for, kill
|
||||||
|
|
||||||
|
tvGen : (look, for : Str) -> TV ; -- look for, talk about
|
||||||
|
tvDir : V -> TV ; -- switch off
|
||||||
|
tvGenDir : (kill : Str) -> TV ; -- kill
|
||||||
|
|
||||||
|
-- Regular two-place verbs with a particle.
|
||||||
|
|
||||||
|
tvPartReg : Str -> Str -> Str -> TV ; -- get, along, with
|
||||||
|
|
||||||
|
-- The definitions should not bother the user of the API. So they are
|
||||||
|
-- hidden from the document.
|
||||||
|
--.
|
||||||
|
|
||||||
|
human = Hum ;
|
||||||
|
nonhuman = NoHum ;
|
||||||
|
-- singular defined in types.Eng
|
||||||
|
-- plural defined in types.Eng
|
||||||
|
|
||||||
|
nominative = Nom ;
|
||||||
|
|
||||||
|
mkN = \man,men,man's,men's,g -> mkNoun man men man's men's ** {g = g} ;
|
||||||
|
nReg = addGenN nounReg ;
|
||||||
|
nKiss = addGenN nounS ;
|
||||||
|
nFly = \fly -> addGenN nounY (Predef.tk 1 fly) ;
|
||||||
|
nMan = \man,men -> mkN man men (man + "'s") (men + "'s") ;
|
||||||
|
nHero = nKiss ;
|
||||||
|
nSheep = \sheep -> nMan sheep sheep ;
|
||||||
|
|
||||||
|
nHuman = \s -> nGen s Hum ;
|
||||||
|
nNonhuman = \s -> nGen s NoHum ;
|
||||||
|
|
||||||
|
nGen : Str -> Gender -> N = \fly,g -> let {
|
||||||
|
fl = Predef.tk 1 fly ;
|
||||||
|
y = Predef.dp 1 fly ;
|
||||||
|
eqy = ifTok (Str -> Gender -> N) y
|
||||||
|
} in
|
||||||
|
eqy "y" nFly (
|
||||||
|
eqy "s" nKiss (
|
||||||
|
eqy "z" nKiss (
|
||||||
|
nReg))) fly g ;
|
||||||
|
|
||||||
|
mkFun = \n,p -> n ** {s2 = p} ;
|
||||||
|
funNonhuman = \s -> mkFun (nNonhuman s) "of" ;
|
||||||
|
funHuman = \s -> mkFun (nHuman s) "of" ;
|
||||||
|
|
||||||
|
pnReg = nameReg ;
|
||||||
|
|
||||||
|
cnNonhuman = \s -> UseN (nGen s nonhuman) ;
|
||||||
|
cnHuman = \s -> UseN (nGen s human) ;
|
||||||
|
npReg = \s -> UsePN (pnReg s) ;
|
||||||
|
|
||||||
|
addGenN : (Str -> CommonNoun) -> Str -> Gender -> N = \f ->
|
||||||
|
\s,g -> f s ** {g = g} ;
|
||||||
|
|
||||||
|
mkAdj1 = simpleAdj ;
|
||||||
|
mkAdj2 = \s,p -> simpleAdj s ** {s2 = p} ;
|
||||||
|
mkAdjDeg = mkAdjDegr ;
|
||||||
|
aReg = adjDegrReg ;
|
||||||
|
aHappy = \happy -> adjDegrY (Predef.tk 1 happy) ;
|
||||||
|
aFat = \fat -> let {fatt = fat + Predef.dp 1 fat} in
|
||||||
|
mkAdjDeg fat (fatt + "er") (fatt + "est") ;
|
||||||
|
aRidiculous = adjDegrLong ;
|
||||||
|
apReg = \s -> AdjP1 (mkAdj1 s) ;
|
||||||
|
|
||||||
|
mkV = \go,goes -> verbNoPart (mkVerbP3 goes go) ;
|
||||||
|
vReg = \run -> mkV run (run + "s") ;
|
||||||
|
vKiss = \kiss -> mkV kiss (kiss + "es") ;
|
||||||
|
vFly = \fly -> mkV fly (Predef.tk 1 fly + "ies") ;
|
||||||
|
vGo = vKiss ;
|
||||||
|
|
||||||
|
vGen = \fly -> let {
|
||||||
|
fl = Predef.tk 1 fly ;
|
||||||
|
y = Predef.dp 1 fly ;
|
||||||
|
eqy = ifTok (Str -> V) y
|
||||||
|
} in
|
||||||
|
eqy "y" vFly (
|
||||||
|
eqy "s" vKiss (
|
||||||
|
eqy "z" vKiss (
|
||||||
|
vReg))) fly ;
|
||||||
|
|
||||||
|
vPart = \go, goes, up -> verbPart (mkVerbP3 goes go) up ;
|
||||||
|
vPartReg = \get, up -> verbPart (regVerbP3 get) up ;
|
||||||
|
|
||||||
|
mkTV = \v,p -> v ** {s3 = p} ;
|
||||||
|
tvPartReg = \get, along, with -> mkTV (vPartReg get along) with ;
|
||||||
|
|
||||||
|
vBe = verbBe ;
|
||||||
|
vHave = mkV "have" "has" ;
|
||||||
|
|
||||||
|
tvGen = \s,p -> mkTV (vGen s) p ;
|
||||||
|
tvDir = \v -> mkTV v [] ;
|
||||||
|
tvGenDir = \s -> tvDir (vGen s) ;
|
||||||
|
|
||||||
|
} ;
|
||||||
83
grammars/resource/english/Predication.gf
Normal file
83
grammars/resource/english/Predication.gf
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
|
||||||
|
--1 A Small Predication Library
|
||||||
|
--
|
||||||
|
-- (c) Aarne Ranta 2003 under Gnu GPL.
|
||||||
|
--
|
||||||
|
-- This library is built on a language-independent API of
|
||||||
|
-- resource grammars. It has a common part, the type signatures
|
||||||
|
-- (defined here), and language-dependent parts. The user of
|
||||||
|
-- the library should only have to look at the type signatures.
|
||||||
|
|
||||||
|
resource Predication = open English in {
|
||||||
|
|
||||||
|
-- We first define a set of predication patterns.
|
||||||
|
|
||||||
|
oper
|
||||||
|
predV1 : V -> NP -> S ; -- one-place verb: "John walks"
|
||||||
|
predV2 : TV -> NP -> NP -> S ; -- two-place verb: "John loves Mary"
|
||||||
|
predVColl : V -> NP -> NP -> S ; -- collective verb: "John and Mary fight"
|
||||||
|
predA1 : Adj1 -> NP -> S ; -- one-place adjective: "John is old"
|
||||||
|
predA2 : Adj2 -> NP -> NP -> S ; -- two-place adj: "John is married to Mary"
|
||||||
|
predAComp : AdjDeg -> NP -> NP -> S ; -- compar adj: "John is older than Mary"
|
||||||
|
predAColl : Adj1 -> NP -> NP -> S ; -- collective adj: "John and Mary are married"
|
||||||
|
predN1 : N -> NP -> S ; -- one-place noun: "John is a man"
|
||||||
|
predN2 : Fun -> NP -> NP -> S ; -- two-place noun: "John is a lover of Mary"
|
||||||
|
predNColl : N -> NP -> NP -> S ; -- collective noun: "John and Mary are lovers"
|
||||||
|
|
||||||
|
-- Individual-valued function applications.
|
||||||
|
|
||||||
|
appFun1 : Fun -> NP -> NP ; -- one-place function: "the successor of x"
|
||||||
|
appFunColl : Fun -> NP -> NP -> NP ; -- collective function: "the sum of x and y"
|
||||||
|
|
||||||
|
-- Families of types, expressed by common nouns depending on arguments.
|
||||||
|
|
||||||
|
appFam1 : Fun -> NP -> CN ; -- one-place family: "divisor of x"
|
||||||
|
appFamColl : Fun -> NP -> NP -> CN ; -- collective family: "path between x and y"
|
||||||
|
|
||||||
|
-- Type constructor, similar to a family except that the argument is a type.
|
||||||
|
|
||||||
|
constrTyp1 : Fun -> CN -> CN ;
|
||||||
|
|
||||||
|
-- Logical connectives on two sentences.
|
||||||
|
|
||||||
|
conjS : S -> S -> S ;
|
||||||
|
disjS : S -> S -> S ;
|
||||||
|
implS : S -> S -> S ;
|
||||||
|
|
||||||
|
-- As an auxiliary, we need two-place conjunction of names ("John and Mary"),
|
||||||
|
-- used in collective predication.
|
||||||
|
|
||||||
|
conjNP : NP -> NP -> NP ;
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
---- what follows should be an implementation of the preceding
|
||||||
|
|
||||||
|
oper
|
||||||
|
predV1 = \F, x -> PredVP x (PosV F) ;
|
||||||
|
predV2 = \F, x, y -> PredVP x (PosTV F y) ;
|
||||||
|
predVColl = \F, x, y -> PredVP (conjNP x y) (PosV F) ;
|
||||||
|
predA1 = \F, x -> PredVP x (PosA F) ;
|
||||||
|
predA2 = \F, x, y -> PredVP x (PosA (ComplAdj F y)) ;
|
||||||
|
predAComp = \F, x, y -> PredVP x (PosA (ComparAdjP F y)) ;
|
||||||
|
predAColl = \F, x, y -> PredVP (conjNP x y) (PosA F) ;
|
||||||
|
predN1 = \F, x -> PredVP x (PosCN (UseN F)) ;
|
||||||
|
predN2 = \F, x, y -> PredVP x (PosCN (AppFun F y)) ;
|
||||||
|
predNColl = \F, x, y -> PredVP (conjNP x y) (PosCN (UseN F)) ;
|
||||||
|
|
||||||
|
appFun1 = \f, x -> DefOneNP (AppFun f x) ;
|
||||||
|
appFunColl = \f, x, y -> DefOneNP (AppFun f (conjNP x y)) ;
|
||||||
|
|
||||||
|
appFam1 = \F, x -> AppFun F x ;
|
||||||
|
appFamColl = \F, x, y -> AppFun F (conjNP x y) ;
|
||||||
|
|
||||||
|
conjS = \A, B -> ConjS AndConj (TwoS A B) ;
|
||||||
|
disjS = \A, B -> ConjS OrConj (TwoS A B) ;
|
||||||
|
implS = \A, B -> SubjS IfSubj A B ;
|
||||||
|
|
||||||
|
constrTyp1 = \F, A -> AppFun F (IndefManyNP A) ;
|
||||||
|
|
||||||
|
conjNP = \x, y -> ConjNP AndConj (TwoNP x y) ;
|
||||||
|
|
||||||
|
} ;
|
||||||
195
grammars/resource/english/ResEng.gf
Normal file
195
grammars/resource/english/ResEng.gf
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
--1 The Top-Level English Resource Grammar
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002 -- 2003
|
||||||
|
--
|
||||||
|
-- This is the English concrete syntax of the multilingual resource
|
||||||
|
-- grammar. Most of the work is done in the file $syntax.Eng.gf$.
|
||||||
|
-- However, for the purpose of documentation, we make here explicit the
|
||||||
|
-- linearization types of each category, so that their structures and
|
||||||
|
-- dependencies can be seen.
|
||||||
|
-- Another substantial part are the linearization rules of some
|
||||||
|
-- structural words.
|
||||||
|
--
|
||||||
|
-- The users of the resource grammar should not look at this file for the
|
||||||
|
-- linearization rules, which are in fact hidden in the document version.
|
||||||
|
-- They should use $resource.Abs.gf$ to access the syntactic rules.
|
||||||
|
-- This file can be consulted in those, hopefully rare, occasions in which
|
||||||
|
-- one has to know how the syntactic categories are
|
||||||
|
-- implemented. The parameter types are defined in $types.Eng.gf$.
|
||||||
|
|
||||||
|
concrete ResEng of ResAbs = open Prelude, Syntax in {
|
||||||
|
|
||||||
|
flags
|
||||||
|
startcat=Phr ;
|
||||||
|
parser=chart ;
|
||||||
|
|
||||||
|
lincat
|
||||||
|
N = CommNoun ;
|
||||||
|
-- = {s : Number => Case => Str}
|
||||||
|
CN = CommNounPhrase ;
|
||||||
|
-- = CommNoun ** {g : Gender}
|
||||||
|
NP = {s : NPForm => Str ; n : Number ; p : Person} ;
|
||||||
|
PN = {s : Case => Str} ;
|
||||||
|
Det = {s : Str ; n : Number} ;
|
||||||
|
Fun = CommNounPhrase ** {s2 : Preposition} ;
|
||||||
|
|
||||||
|
Adj1 = Adjective ;
|
||||||
|
-- = {s : Str}
|
||||||
|
Adj2 = Adjective ** {s2 : Preposition} ;
|
||||||
|
AdjDeg = {s : Degree => Str} ;
|
||||||
|
AP = Adjective ** {p : Bool} ;
|
||||||
|
|
||||||
|
V = Verb ;
|
||||||
|
-- = {s : VForm => Str ; s1 : Particle}
|
||||||
|
VP = {s : VForm => Str ; s2 : Number => Str ; isAux : Bool} ;
|
||||||
|
TV = Verb ** {s3 : Preposition} ;
|
||||||
|
VS = Verb ;
|
||||||
|
|
||||||
|
AdV = {s : Str ; isPost : Bool} ;
|
||||||
|
|
||||||
|
S = {s : Str} ;
|
||||||
|
Slash = {s : Bool => Str ; s2 : Preposition} ;
|
||||||
|
RP = {s : Gender => Number => NPForm => Str} ;
|
||||||
|
RC = {s : Gender => Number => Str} ;
|
||||||
|
|
||||||
|
IP = {s : NPForm => Str ; n : Number} ;
|
||||||
|
Qu = {s : QuestForm => Str} ;
|
||||||
|
Imp = {s : Number => Str} ;
|
||||||
|
Phr = {s : Str} ;
|
||||||
|
|
||||||
|
Conj = {s : Str ; n : Number} ;
|
||||||
|
ConjD = {s1 : Str ; s2 : Str ; n : Number} ;
|
||||||
|
|
||||||
|
ListS = {s1 : Str ; s2 : Str} ;
|
||||||
|
ListAP = {s1 : Str ; s2 : Str ; p : Bool} ;
|
||||||
|
ListNP = {s1,s2 : NPForm => Str ; n : Number ; p : Person} ;
|
||||||
|
|
||||||
|
--.
|
||||||
|
|
||||||
|
lin
|
||||||
|
UseN = noun2CommNounPhrase ;
|
||||||
|
ModAdj = modCommNounPhrase ;
|
||||||
|
ModGenOne = npGenDet singular ;
|
||||||
|
ModGenMany = npGenDet plural ;
|
||||||
|
UsePN = nameNounPhrase ;
|
||||||
|
UseFun = funAsCommNounPhrase ;
|
||||||
|
AppFun = appFunComm ;
|
||||||
|
AdjP1 = adj2adjPhrase ;
|
||||||
|
ComplAdj = complAdj ;
|
||||||
|
PositAdjP = positAdjPhrase ;
|
||||||
|
ComparAdjP = comparAdjPhrase ;
|
||||||
|
SuperlNP = superlNounPhrase ;
|
||||||
|
|
||||||
|
DetNP = detNounPhrase ;
|
||||||
|
IndefOneNP = indefNounPhrase singular ;
|
||||||
|
IndefManyNP = indefNounPhrase plural ;
|
||||||
|
DefOneNP = defNounPhrase singular ;
|
||||||
|
DefManyNP = defNounPhrase plural ;
|
||||||
|
|
||||||
|
PredVP = predVerbPhrase ;
|
||||||
|
PosV = predVerb True ;
|
||||||
|
NegV = predVerb False ;
|
||||||
|
PosA = predAdjective True ;
|
||||||
|
NegA = predAdjective False ;
|
||||||
|
PosCN = predCommNoun True ;
|
||||||
|
NegCN = predCommNoun False ;
|
||||||
|
PosTV = complTransVerb True ;
|
||||||
|
NegTV = complTransVerb False ;
|
||||||
|
PosNP = predNounPhrase True ;
|
||||||
|
NegNP = predNounPhrase False ;
|
||||||
|
PosVS = complSentVerb True ;
|
||||||
|
NegVS = complSentVerb False ;
|
||||||
|
|
||||||
|
|
||||||
|
AdvVP = adVerbPhrase ;
|
||||||
|
LocNP = locativeNounPhrase ;
|
||||||
|
AdvCN = advCommNounPhrase ;
|
||||||
|
|
||||||
|
PosSlashTV = slashTransVerb True ;
|
||||||
|
NegSlashTV = slashTransVerb False ;
|
||||||
|
|
||||||
|
IdRP = identRelPron ;
|
||||||
|
FunRP = funRelPron ;
|
||||||
|
RelVP = relVerbPhrase ;
|
||||||
|
RelSlash = relSlash ;
|
||||||
|
ModRC = modRelClause ;
|
||||||
|
RelSuch = relSuch ;
|
||||||
|
|
||||||
|
WhoOne = intPronWho singular ;
|
||||||
|
WhoMany = intPronWho plural ;
|
||||||
|
WhatOne = intPronWhat singular ;
|
||||||
|
WhatMany = intPronWhat plural ;
|
||||||
|
FunIP = funIntPron ;
|
||||||
|
NounIPOne = nounIntPron singular ;
|
||||||
|
NounIPMany = nounIntPron plural ;
|
||||||
|
|
||||||
|
QuestVP = questVerbPhrase ;
|
||||||
|
IntVP = intVerbPhrase ;
|
||||||
|
IntSlash = intSlash ;
|
||||||
|
QuestAdv = questAdverbial ;
|
||||||
|
|
||||||
|
ImperVP = imperVerbPhrase ;
|
||||||
|
|
||||||
|
IndicPhrase = indicUtt ;
|
||||||
|
QuestPhrase = interrogUtt ;
|
||||||
|
ImperOne = imperUtterance singular ;
|
||||||
|
ImperMany = imperUtterance plural ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
TwoS = twoSentence ;
|
||||||
|
ConsS = consSentence ;
|
||||||
|
ConjS = conjunctSentence ;
|
||||||
|
ConjDS = conjunctDistrSentence ;
|
||||||
|
|
||||||
|
TwoAP = twoAdjPhrase ;
|
||||||
|
ConsAP = consAdjPhrase ;
|
||||||
|
ConjAP = conjunctAdjPhrase ;
|
||||||
|
ConjDAP = conjunctDistrAdjPhrase ;
|
||||||
|
|
||||||
|
TwoNP = twoNounPhrase ;
|
||||||
|
ConsNP = consNounPhrase ;
|
||||||
|
ConjNP = conjunctNounPhrase ;
|
||||||
|
ConjDNP = conjunctDistrNounPhrase ;
|
||||||
|
|
||||||
|
SubjS = subjunctSentence ;
|
||||||
|
SubjImper = subjunctImperative ;
|
||||||
|
SubjQu = subjunctQuestion ;
|
||||||
|
|
||||||
|
PhrNP = useNounPhrase ;
|
||||||
|
PhrOneCN = useCommonNounPhrase singular ;
|
||||||
|
PhrManyCN = useCommonNounPhrase plural ;
|
||||||
|
PhrIP ip = ip ;
|
||||||
|
PhrIAdv ia = ia ;
|
||||||
|
|
||||||
|
|
||||||
|
lin
|
||||||
|
INP = pronI ;
|
||||||
|
ThouNP = pronYouSg ;
|
||||||
|
HeNP = pronHe ;
|
||||||
|
SheNP = pronShe ;
|
||||||
|
WeNP = pronWe ;
|
||||||
|
YeNP = pronYouPl ;
|
||||||
|
YouNP = pronYouSg ;
|
||||||
|
TheyNP = pronThey ;
|
||||||
|
|
||||||
|
EveryDet = everyDet ;
|
||||||
|
AllDet = allDet ;
|
||||||
|
WhichDet = whichDet ;
|
||||||
|
MostDet = mostDet ;
|
||||||
|
|
||||||
|
HowIAdv = ss "how" ;
|
||||||
|
WhenIAdv = ss "when" ;
|
||||||
|
WhereIAdv = ss "where" ;
|
||||||
|
WhyIAdv = ss "why" ;
|
||||||
|
|
||||||
|
AndConj = ss "and" ** {n = Pl} ;
|
||||||
|
OrConj = ss "or" ** {n = Sg} ;
|
||||||
|
BothAnd = sd2 "both" "and" ** {n = Pl} ;
|
||||||
|
EitherOr = sd2 "either" "or" ** {n = Sg} ;
|
||||||
|
NeitherNor = sd2 "neither" "nor" ** {n = Sg} ;
|
||||||
|
IfSubj = ss "if" ;
|
||||||
|
WhenSubj = ss "when" ;
|
||||||
|
|
||||||
|
PhrYes = ss "Yes." ;
|
||||||
|
PhrNo = ss "No." ;
|
||||||
|
} ;
|
||||||
25
grammars/resource/english/RestaurantEng.gf
Normal file
25
grammars/resource/english/RestaurantEng.gf
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
concrete RestaurantEng of Restaurant =
|
||||||
|
DatabaseEng ** open Prelude,Paradigms,DatabaseRes in {
|
||||||
|
|
||||||
|
lin
|
||||||
|
Restaurant = cnNonhuman "restaurant" ;
|
||||||
|
Bar = cnNonhuman "bar" ;
|
||||||
|
French = apReg "French" ;
|
||||||
|
Italian = apReg "Italian" ;
|
||||||
|
Indian = apReg "Indian" ;
|
||||||
|
Japanese = apReg "Japanese" ;
|
||||||
|
|
||||||
|
address = funNonhuman "address" ;
|
||||||
|
phone = funNonhuman ["number"] ; --- phone
|
||||||
|
priceLevel = funNonhuman ["level"] ; --- price
|
||||||
|
|
||||||
|
Cheap = aReg "cheap" ;
|
||||||
|
Expensive = aRidiculous "expensive" ;
|
||||||
|
|
||||||
|
WhoRecommend rest = mkSentSame (ss (["who recommended"] ++ rest.s ! nominative)) ;
|
||||||
|
WhoHellRecommend rest =
|
||||||
|
mkSentSame (ss (["who the hell recommended"] ++ rest.s ! nominative)) ;
|
||||||
|
|
||||||
|
LucasCarton = pnReg ["Lucas Carton"] ;
|
||||||
|
|
||||||
|
} ;
|
||||||
848
grammars/resource/english/Syntax.gf
Normal file
848
grammars/resource/english/Syntax.gf
Normal file
@@ -0,0 +1,848 @@
|
|||||||
|
--1 A Small English Resource Syntax
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002
|
||||||
|
--
|
||||||
|
-- This resource grammar contains definitions needed to construct
|
||||||
|
-- indicative, interrogative, and imperative sentences in English.
|
||||||
|
--
|
||||||
|
-- The following files are presupposed:
|
||||||
|
|
||||||
|
resource Syntax = Morpho ** open Prelude, (CO = Coordination) in {
|
||||||
|
|
||||||
|
--2 Common Nouns
|
||||||
|
--
|
||||||
|
-- Simple common nouns are defined as the type $CommNoun$ in $morpho.Deu.gf$.
|
||||||
|
|
||||||
|
--3 Common noun phrases
|
||||||
|
|
||||||
|
-- To the common nouns of morphology,
|
||||||
|
-- we add natural gender (human/nonhuman) which is needed in syntactic
|
||||||
|
-- combinations (e.g. "man who runs" - "program which runs").
|
||||||
|
|
||||||
|
oper
|
||||||
|
CommNoun = CommonNoun ** {g : Gender} ;
|
||||||
|
|
||||||
|
CommNounPhrase = CommNoun ;
|
||||||
|
|
||||||
|
noun2CommNounPhrase : CommNoun -> CommNounPhrase = \man ->
|
||||||
|
man ;
|
||||||
|
|
||||||
|
cnGen : CommonNoun -> Gender -> CommNoun = \cn,g ->
|
||||||
|
cn ** {g = g} ;
|
||||||
|
|
||||||
|
cnHum : CommonNoun -> CommNoun = \cn ->
|
||||||
|
cnGen cn Hum ;
|
||||||
|
cnNoHum : CommonNoun -> CommNoun = \cn ->
|
||||||
|
cnGen cn NoHum ;
|
||||||
|
|
||||||
|
--2 Noun phrases
|
||||||
|
--
|
||||||
|
-- The worst case is pronouns, which have inflection in the possessive forms.
|
||||||
|
-- Proper names are a special case.
|
||||||
|
|
||||||
|
NounPhrase : Type = Pronoun ;
|
||||||
|
|
||||||
|
nameNounPhrase : ProperName -> NounPhrase = \john ->
|
||||||
|
{s = \\c => john.s ! toCase c ; n = Sg ; p = P3} ;
|
||||||
|
|
||||||
|
--2 Determiners
|
||||||
|
--
|
||||||
|
-- Determiners are inflected according to the nouns they determine.
|
||||||
|
-- The determiner is not inflected.
|
||||||
|
Determiner : Type = {s : Str ; n : Number} ;
|
||||||
|
|
||||||
|
detNounPhrase : Determiner -> CommNounPhrase -> NounPhrase = \every, man ->
|
||||||
|
{s = \\c => every.s ++ man.s ! every.n ! toCase c ;
|
||||||
|
n = every.n ;
|
||||||
|
p = P3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
mkDeterminer : Number -> Str -> Determiner = \n,det ->
|
||||||
|
{s = det ;
|
||||||
|
n = n
|
||||||
|
} ;
|
||||||
|
|
||||||
|
everyDet = mkDeterminer Sg "every" ;
|
||||||
|
allDet = mkDeterminer Pl "all" ;
|
||||||
|
mostDet = mkDeterminer Pl "most" ;
|
||||||
|
aDet = mkDeterminer Sg artIndef ;
|
||||||
|
plDet = mkDeterminer Pl [] ;
|
||||||
|
theSgDet = mkDeterminer Sg "the" ;
|
||||||
|
thePlDet = mkDeterminer Pl "the" ;
|
||||||
|
anySgDet = mkDeterminer Sg "any" ;
|
||||||
|
anyPlDet = mkDeterminer Pl "any" ;
|
||||||
|
|
||||||
|
whichSgDet = mkDeterminer Sg "which" ;
|
||||||
|
whichPlDet = mkDeterminer Pl "which" ;
|
||||||
|
|
||||||
|
whichDet = whichSgDet ; --- API
|
||||||
|
|
||||||
|
indefNoun : Number -> CommNoun -> Str = \n,man ->
|
||||||
|
(indefNounPhrase n man).s ! NomP ;
|
||||||
|
|
||||||
|
indefNounPhrase : Number -> CommNounPhrase -> NounPhrase = \n,man ->
|
||||||
|
{s = \\c => case n of {
|
||||||
|
Sg => artIndef ++ man.s ! n ! toCase c ;
|
||||||
|
Pl => man.s ! n ! toCase c
|
||||||
|
} ;
|
||||||
|
n = n ; p = P3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
defNounPhrase : Number -> CommNounPhrase -> NounPhrase = \n,car ->
|
||||||
|
{s = \\c => artDef ++ car.s ! n ! toCase c ; n = n ; p = P3} ;
|
||||||
|
|
||||||
|
-- Genitives of noun phrases can be used like determiners, to build noun phrases.
|
||||||
|
-- The number argument makes the difference between "my house" - "my houses".
|
||||||
|
--
|
||||||
|
-- We have the variation "the car of John / the car of John's / John's car"
|
||||||
|
|
||||||
|
npGenDet : Number -> NounPhrase -> CommNounPhrase -> NounPhrase =
|
||||||
|
\n,john,car ->
|
||||||
|
{s = \\c => variants {
|
||||||
|
artDef ++ car.s ! n ! Nom ++ "of" ++ john.s ! GenSP ;
|
||||||
|
john.s ! GenP ++ car.s ! n ! toCase c
|
||||||
|
} ;
|
||||||
|
n = n ;
|
||||||
|
p = P3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- *Bare plural noun phrases* like "men", "good cars", are built without a
|
||||||
|
-- determiner word.
|
||||||
|
|
||||||
|
plurDet : CommNounPhrase -> NounPhrase = \cn ->
|
||||||
|
{s = \\c => cn.s ! plural ! toCase c ;
|
||||||
|
p = P3 ;
|
||||||
|
n = Pl
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Adjectives
|
||||||
|
--
|
||||||
|
-- Adjectival phrases have a parameter $p$ telling if they are prefixed ($True$) or
|
||||||
|
-- postfixed (complex APs).
|
||||||
|
|
||||||
|
AdjPhrase : Type = Adjective ** {p : Bool} ;
|
||||||
|
|
||||||
|
adj2adjPhrase : Adjective -> AdjPhrase = \new -> new ** {p = True} ;
|
||||||
|
|
||||||
|
simpleAdjPhrase : Str -> AdjPhrase = \French ->
|
||||||
|
adj2adjPhrase (simpleAdj French) ;
|
||||||
|
|
||||||
|
--3 Comparison adjectives
|
||||||
|
--
|
||||||
|
-- Each of the comparison forms has a characteristic use:
|
||||||
|
--
|
||||||
|
-- Positive forms are used alone, as adjectival phrases ("big").
|
||||||
|
|
||||||
|
positAdjPhrase : AdjDegr -> AdjPhrase = \big ->
|
||||||
|
adj2adjPhrase (ss (big.s ! Pos)) ;
|
||||||
|
|
||||||
|
-- Comparative forms are used with an object of comparison, as
|
||||||
|
-- adjectival phrases ("bigger then you").
|
||||||
|
|
||||||
|
comparAdjPhrase : AdjDegr -> NounPhrase -> AdjPhrase = \big, you ->
|
||||||
|
{s = big.s ! Comp ++ "than" ++ you.s ! NomP ;
|
||||||
|
p = False
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Superlative forms are used with a modified noun, picking out the
|
||||||
|
-- maximal representative of a domain ("the biggest house").
|
||||||
|
|
||||||
|
superlNounPhrase : AdjDegr -> CommNoun -> NounPhrase = \big, house ->
|
||||||
|
{s = \\c => "the" ++ big.s ! Sup ++ house.s ! Sg ! toCase c ;
|
||||||
|
n = Sg ;
|
||||||
|
p = P3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Two-place adjectives
|
||||||
|
--
|
||||||
|
-- A two-place adjective is an adjective with a preposition used before
|
||||||
|
-- the complement.
|
||||||
|
|
||||||
|
Preposition = Str ;
|
||||||
|
|
||||||
|
AdjCompl = Adjective ** {s2 : Preposition} ;
|
||||||
|
|
||||||
|
complAdj : AdjCompl -> NounPhrase -> AdjPhrase = \related,john ->
|
||||||
|
{s = related.s ++ related.s2 ++ john.s ! AccP ;
|
||||||
|
p = False
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Modification of common nouns
|
||||||
|
--
|
||||||
|
-- The two main functions of adjective are in predication ("John is old")
|
||||||
|
-- and in modification ("an old man"). Predication will be defined
|
||||||
|
-- later, in the chapter on verbs.
|
||||||
|
--
|
||||||
|
-- Modification must pay attention to pre- and post-noun
|
||||||
|
-- adjectives: "big car"/"car bigger than X"
|
||||||
|
|
||||||
|
modCommNounPhrase : AdjPhrase -> CommNounPhrase -> CommNounPhrase = \big, car ->
|
||||||
|
{s = \\n => if_then_else (Case => Str) big.p
|
||||||
|
(\\c => big.s ++ car.s ! n ! c)
|
||||||
|
(table {Nom => car.s ! n ! Nom ++ big.s ; Gen => variants {}}) ;
|
||||||
|
g = car.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Function expressions
|
||||||
|
|
||||||
|
-- A function expression is a common noun together with the
|
||||||
|
-- preposition prefixed to its argument ("mother of x").
|
||||||
|
-- The type is analogous to two-place adjectives and transitive verbs.
|
||||||
|
|
||||||
|
Function = CommNounPhrase ** {s2 : Preposition} ;
|
||||||
|
|
||||||
|
-- The application of a function gives, in the first place, a common noun:
|
||||||
|
-- "mother/mothers of John". From this, other rules of the resource grammar
|
||||||
|
-- give noun phrases, such as "the mother of John", "the mothers of John",
|
||||||
|
-- "the mothers of John and Mary", and "the mother of John and Mary" (the
|
||||||
|
-- latter two corresponding to distributive and collective functions,
|
||||||
|
-- respectively). Semantics will eventually tell when each
|
||||||
|
-- of the readings is meaningful.
|
||||||
|
|
||||||
|
appFunComm : Function -> NounPhrase -> CommNounPhrase = \mother,john ->
|
||||||
|
{s = \\n => table {
|
||||||
|
Gen => nonExist ;
|
||||||
|
_ => mother.s ! n ! Nom ++ mother.s2 ++ john.s ! GenSP
|
||||||
|
} ;
|
||||||
|
g = mother.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- It is possible to use a function word as a common noun; the semantics is
|
||||||
|
-- often existential or indexical.
|
||||||
|
|
||||||
|
funAsCommNounPhrase : Function -> CommNounPhrase =
|
||||||
|
noun2CommNounPhrase ;
|
||||||
|
|
||||||
|
-- The following is an aggregate corresponding to the original function application
|
||||||
|
-- producing "John's mother" and "the mother of John". It does not appear in the
|
||||||
|
-- resource grammar API any longer.
|
||||||
|
|
||||||
|
appFun : Bool -> Function -> NounPhrase -> NounPhrase = \coll, mother,john ->
|
||||||
|
let {n = john.n ; nf = if_then_else Number coll Sg n} in
|
||||||
|
variants {
|
||||||
|
defNounPhrase nf (appFunComm mother john) ;
|
||||||
|
npGenDet nf john mother
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- The commonest case is functions with the preposition "of".
|
||||||
|
|
||||||
|
funOf : CommNoun -> Function = \mother ->
|
||||||
|
mother ** {s2 = "of"} ;
|
||||||
|
|
||||||
|
funOfReg : Str -> Gender -> Function = \mother,g ->
|
||||||
|
funOf (nounReg mother ** {g = g}) ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--2 Verbs
|
||||||
|
--
|
||||||
|
--3 Verb phrases
|
||||||
|
--
|
||||||
|
-- Verb phrases are discontinuous: the two parts of a verb phrase are
|
||||||
|
-- (s) an inflected verb, (s2) infinitive and complement.
|
||||||
|
-- For instance: "doesn't" - "walk" ; "isn't" - "old" ; "is" - "a man"
|
||||||
|
-- There's also a parameter telling if the verb is an auxiliary:
|
||||||
|
-- this is needed in question.
|
||||||
|
|
||||||
|
VerbPhrase = VerbP3 ** {s2 : Number => Str ; isAux : Bool} ;
|
||||||
|
|
||||||
|
-- From the inflection table, we selecting the finite form as function
|
||||||
|
-- of person and number:
|
||||||
|
|
||||||
|
indicVerb : VerbP3 -> Person -> Number -> Str = \v,p,n -> case n of {
|
||||||
|
Sg => v.s ! Indic p ;
|
||||||
|
Pl => v.s ! Indic P2
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- A simple verb can be made into a verb phrase with an empty complement.
|
||||||
|
-- There are two versions, depending on if we want to negate the verb.
|
||||||
|
-- N.B. negation is *not* a function applicable to a verb phrase, since
|
||||||
|
-- double negations with "don't" are not grammatical.
|
||||||
|
|
||||||
|
predVerb : Bool -> Verb -> VerbPhrase = \b,walk ->
|
||||||
|
if_then_else VerbPhrase b
|
||||||
|
{s = \\v => walk.s ! v ++ walk.s1 ;
|
||||||
|
s2 = \\_ => [] ;
|
||||||
|
isAux = False
|
||||||
|
}
|
||||||
|
{s = \\v => contractNot (verbP3Do.s ! v) ;
|
||||||
|
s2 = \\_ => walk.s ! InfImp ++ walk.s1 ;
|
||||||
|
isAux = True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Sometimes we want to extract the verb part of a verb phrase.
|
||||||
|
|
||||||
|
verbOfPhrase : VerbPhrase -> VerbP3 = \v -> {s = v.s} ;
|
||||||
|
|
||||||
|
-- Verb phrases can also be formed from adjectives ("is old"),
|
||||||
|
-- common nouns ("is a man"), and noun phrases ("ist John").
|
||||||
|
-- The third rule is overgenerating: "is every man" has to be ruled out
|
||||||
|
-- on semantic grounds.
|
||||||
|
|
||||||
|
predAdjective : Bool -> Adjective -> VerbPhrase = \b,old ->
|
||||||
|
{s = beOrNotBe b ;
|
||||||
|
s2 = \\_ => old.s ;
|
||||||
|
isAux = True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
predCommNoun : Bool -> CommNoun -> VerbPhrase = \b,man ->
|
||||||
|
{s = beOrNotBe b ;
|
||||||
|
s2 = \\n => indefNoun n man ;
|
||||||
|
isAux = True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
predNounPhrase : Bool -> NounPhrase -> VerbPhrase = \b,john ->
|
||||||
|
{s = beOrNotBe b ;
|
||||||
|
s2 = \\_ => john.s ! NomP ;
|
||||||
|
isAux = True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- We use an auxiliary giving all forms of "be".
|
||||||
|
|
||||||
|
beOrNotBe : Bool -> (VForm => Str) = \b ->
|
||||||
|
if_then_else (VForm => Str) b
|
||||||
|
verbBe.s
|
||||||
|
(table {
|
||||||
|
InfImp => contractNot "do" ++ "be" ;
|
||||||
|
Indic P1 => "am" ++ "not" ;
|
||||||
|
v => contractNot (verbBe.s ! v)
|
||||||
|
}) ;
|
||||||
|
|
||||||
|
--3 Transitive verbs
|
||||||
|
--
|
||||||
|
-- Transitive verbs are verbs with a preposition for the complement,
|
||||||
|
-- in analogy with two-place adjectives and functions.
|
||||||
|
-- One might prefer to use the term "2-place verb", since
|
||||||
|
-- "transitive" traditionally means that the inherent preposition is empty.
|
||||||
|
-- Such a verb is one with a *direct object*.
|
||||||
|
|
||||||
|
TransVerb : Type = Verb ** {s3 : Preposition} ;
|
||||||
|
|
||||||
|
-- The rule for using transitive verbs is the complementization rule.
|
||||||
|
-- Particles produce free variation: before or after the complement
|
||||||
|
-- ("I switch on the TV" / "I switch the TV on").
|
||||||
|
|
||||||
|
complTransVerb : Bool -> TransVerb -> NounPhrase -> VerbPhrase =
|
||||||
|
\b,lookat,john ->
|
||||||
|
let {lookatjohn = bothWays lookat.s1 (lookat.s3 ++ john.s ! AccP)} in
|
||||||
|
if_then_else VerbPhrase b
|
||||||
|
{s = lookat.s ;
|
||||||
|
s2 = \\_ => lookatjohn ;
|
||||||
|
isAux = False}
|
||||||
|
{s = \\v => contractNot (verbP3Do.s ! v) ;
|
||||||
|
s2 = \\_ => lookat.s ! InfImp ++ lookatjohn ;
|
||||||
|
isAux = True} ;
|
||||||
|
|
||||||
|
|
||||||
|
-- Verbs that take direct object and a particle:
|
||||||
|
mkTransVerbPart : VerbP3 -> Str -> TransVerb = \turn,off ->
|
||||||
|
{s = turn.s ; s1 = off ; s3 = []} ;
|
||||||
|
|
||||||
|
-- Verbs that take prepositional object, no particle:
|
||||||
|
mkTransVerb : VerbP3 -> Str -> TransVerb = \wait,for ->
|
||||||
|
{s = wait.s ; s1 = [] ; s3 = for} ;
|
||||||
|
|
||||||
|
-- Verbs that take direct object, no particle:
|
||||||
|
mkTransVerbDir : VerbP3 -> TransVerb = \love ->
|
||||||
|
mkTransVerbPart love [] ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Adverbials
|
||||||
|
--
|
||||||
|
-- Adverbials are not inflected (we ignore comparison, and treat
|
||||||
|
-- compared adverbials as separate expressions; this could be done another way).
|
||||||
|
-- We distinguish between post- and pre-verbal adverbs.
|
||||||
|
|
||||||
|
Adverb : Type = SS ** {isPost : Bool} ;
|
||||||
|
|
||||||
|
advPre : Str -> Adverb = \seldom -> ss seldom ** {isPost = False} ;
|
||||||
|
advPost : Str -> Adverb = \well -> ss well ** {isPost = True} ;
|
||||||
|
|
||||||
|
-- N.B. this rule generates the cyclic parsing rule $VP#2 ::= VP#2$
|
||||||
|
-- and cannot thus be parsed.
|
||||||
|
|
||||||
|
adVerbPhrase : VerbPhrase -> Adverb -> VerbPhrase = \sings, well ->
|
||||||
|
let {postp = orB well.isPost sings.isAux} in
|
||||||
|
{
|
||||||
|
s = \\v => (if_then_else Str postp [] well.s) ++ sings.s ! v ;
|
||||||
|
s2 = \\n => sings.s2 ! n ++ (if_then_else Str postp well.s []) ;
|
||||||
|
isAux = sings.isAux
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Adverbials are typically generated by prefixing prepositions.
|
||||||
|
-- The rule for creating locative noun phrases by the preposition "in"
|
||||||
|
-- is a little shaky, since other prepositions may be preferred ("on", "at").
|
||||||
|
|
||||||
|
prepPhrase : Preposition -> NounPhrase -> Adverb = \on, it ->
|
||||||
|
advPost (on ++ it.s ! AccP) ;
|
||||||
|
|
||||||
|
locativeNounPhrase : NounPhrase -> Adverb =
|
||||||
|
prepPhrase "in" ;
|
||||||
|
|
||||||
|
-- This is a source of the "mann with a telescope" ambiguity, and may produce
|
||||||
|
-- strange things, like "cars always" (while "cars today" is OK).
|
||||||
|
-- Semantics will have to make finer distinctions among adverbials.
|
||||||
|
--
|
||||||
|
-- N.B. the genitive case created in this way would not make sense.
|
||||||
|
|
||||||
|
advCommNounPhrase : CommNounPhrase -> Adverb -> CommNounPhrase = \car,today ->
|
||||||
|
{s = \\n => table {
|
||||||
|
Nom => car.s ! n ! Nom ++ today.s ;
|
||||||
|
Gen => nonExist
|
||||||
|
} ;
|
||||||
|
g = car.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Sentences
|
||||||
|
--
|
||||||
|
-- Sentences are not inflected in this fragment of English without tense.
|
||||||
|
|
||||||
|
Sentence : Type = SS ;
|
||||||
|
|
||||||
|
-- This is the traditional $S -> NP VP$ rule. It takes care of
|
||||||
|
-- agreement between subject and verb. Recall that the VP may already
|
||||||
|
-- contain negation.
|
||||||
|
|
||||||
|
predVerbPhrase : NounPhrase -> VerbPhrase -> Sentence = \john,walks ->
|
||||||
|
ss (john.s ! NomP ++ indicVerb (verbOfPhrase walks) john.p john.n ++
|
||||||
|
walks.s2 ! john.n) ;
|
||||||
|
|
||||||
|
|
||||||
|
-- This is a macro for simultaneous predication and complementization.
|
||||||
|
|
||||||
|
predTransVerb : Bool -> NounPhrase -> TransVerb -> NounPhrase -> Sentence =
|
||||||
|
\b,you,see,john ->
|
||||||
|
predVerbPhrase you (complTransVerb b see john) ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Sentence-complement verbs
|
||||||
|
--
|
||||||
|
-- Sentence-complement verbs take sentences as complements.
|
||||||
|
|
||||||
|
SentenceVerb : Type = Verb ;
|
||||||
|
|
||||||
|
-- To generate "says that John walks" / "doesn't say that John walks":
|
||||||
|
|
||||||
|
complSentVerb : Bool -> SentenceVerb -> Sentence -> VerbPhrase =
|
||||||
|
\b,say,johnruns ->
|
||||||
|
let {thatjohnruns = optStr "that" ++ johnruns.s} in
|
||||||
|
if_then_else VerbPhrase b
|
||||||
|
{s = say.s ;
|
||||||
|
s2 = \\_ => thatjohnruns ;
|
||||||
|
isAux = False}
|
||||||
|
{s = \\v => contractNot (verbP3Do.s ! v) ;
|
||||||
|
s2 = \\_ => say.s ! InfImp ++ thatjohnruns ;
|
||||||
|
isAux = True} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Sentences missing noun phrases
|
||||||
|
--
|
||||||
|
-- This is one instance of Gazdar's *slash categories*, corresponding to his
|
||||||
|
-- $S/NP$.
|
||||||
|
-- We cannot have - nor would we want to have - a productive slash-category former.
|
||||||
|
-- Perhaps a handful more will be needed.
|
||||||
|
--
|
||||||
|
-- Notice that the slash category has a similar relation to sentences as
|
||||||
|
-- transitive verbs have to verbs: it's like a *sentence taking a complement*.
|
||||||
|
-- However, we need something more to distinguish its use in direct questions:
|
||||||
|
-- not just "you see" but ("whom") "do you see".
|
||||||
|
--
|
||||||
|
-- The particle always follows the verb, but the preposition can fly:
|
||||||
|
-- "whom you make it up with" / "with whom you make it up".
|
||||||
|
|
||||||
|
SentenceSlashNounPhrase = {s : Bool => Str ; s2 : Preposition} ;
|
||||||
|
|
||||||
|
slashTransVerb : Bool -> NounPhrase -> TransVerb -> SentenceSlashNounPhrase =
|
||||||
|
\b,You,lookat ->
|
||||||
|
let {you = You.s ! NomP ;
|
||||||
|
looks = indicVerb {s = lookat.s} You.p You.n ;
|
||||||
|
look = lookat.s ! InfImp ;
|
||||||
|
do = indicVerb verbP3Do You.p You.n ;
|
||||||
|
dont = contractNot do ;
|
||||||
|
up = lookat.s1
|
||||||
|
} in
|
||||||
|
{s = table {
|
||||||
|
True => if_then_else Str b do dont ++ you ++ look ++ up ;
|
||||||
|
False => you ++ if_then_else Str b looks (dont ++ look) ++ up
|
||||||
|
} ;
|
||||||
|
s2 = lookat.s3
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Relative pronouns and relative clauses
|
||||||
|
--
|
||||||
|
-- As described in $types.Eng.gf$, relative pronouns are inflected in
|
||||||
|
-- gender (human/nonhuman), number, and case.
|
||||||
|
--
|
||||||
|
-- We get the simple relative pronoun ("who"/"which"/"whom"/"whose"/"that"/$""$)
|
||||||
|
-- from $morpho.Eng.gf$.
|
||||||
|
|
||||||
|
identRelPron : RelPron = relPron ;
|
||||||
|
|
||||||
|
funRelPron : Function -> RelPron -> RelPron = \mother,which ->
|
||||||
|
{s = \\g,n,c => "the" ++ mother.s ! n ! Nom ++
|
||||||
|
mother.s2 ++ which.s ! g ! n ! GenSP
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Relative clauses can be formed from both verb phrases ("who walks") and
|
||||||
|
-- slash expressions ("whom you see", "on which you sit" / "that you sit on").
|
||||||
|
|
||||||
|
RelClause : Type = {s : Gender => Number => Str} ;
|
||||||
|
|
||||||
|
relVerbPhrase : RelPron -> VerbPhrase -> RelClause = \who,walks ->
|
||||||
|
{s = \\g, n => who.s ! g ! n ! NomP ++
|
||||||
|
indicVerb (verbOfPhrase walks) P3 n ++ walks.s2 ! n
|
||||||
|
} ;
|
||||||
|
|
||||||
|
relSlash : RelPron -> SentenceSlashNounPhrase -> RelClause = \who,yousee ->
|
||||||
|
{s = \\g,n =>
|
||||||
|
let {youSee = yousee.s ! False} in
|
||||||
|
variants {
|
||||||
|
who.s ! g ! n ! AccP ++ youSee ++ yousee.s2 ;
|
||||||
|
yousee.s2 ++ who.s ! g ! n ! GenSP ++ youSee
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- A 'degenerate' relative clause is the one often used in mathematics, e.g.
|
||||||
|
-- "number x such that x is even".
|
||||||
|
|
||||||
|
relSuch : Sentence -> RelClause = \A ->
|
||||||
|
{s = \\_,_ => "such" ++ "that" ++ A.s} ;
|
||||||
|
|
||||||
|
-- The main use of relative clauses is to modify common nouns.
|
||||||
|
-- The result is a common noun, out of which noun phrases can be formed
|
||||||
|
-- by determiners. No comma is used before these relative clause.
|
||||||
|
|
||||||
|
modRelClause : CommNounPhrase -> RelClause -> CommNounPhrase = \man,whoruns ->
|
||||||
|
{s = \\n,c => man.s ! n ! c ++ whoruns.s ! man.g ! n ;
|
||||||
|
g = man.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Interrogative pronouns
|
||||||
|
--
|
||||||
|
-- If relative pronouns are adjective-like, interrogative pronouns are
|
||||||
|
-- noun-phrase-like.
|
||||||
|
|
||||||
|
IntPron : Type = {s : NPForm => Str ; n : Number} ;
|
||||||
|
|
||||||
|
-- In analogy with relative pronouns, we have a rule for applying a function
|
||||||
|
-- to a relative pronoun to create a new one.
|
||||||
|
|
||||||
|
funIntPron : Function -> IntPron -> IntPron = \mother,which ->
|
||||||
|
{s = \\c => "the" ++ mother.s ! which.n ! Nom ++ mother.s2 ++ which.s ! GenSP ;
|
||||||
|
n = which.n
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- There is a variety of simple interrogative pronouns:
|
||||||
|
-- "which house", "who", "what".
|
||||||
|
|
||||||
|
nounIntPron : Number -> CommNounPhrase -> IntPron = \n, car ->
|
||||||
|
{s = \\c => "which" ++ car.s ! n ! toCase c ;
|
||||||
|
n = n
|
||||||
|
} ;
|
||||||
|
|
||||||
|
intPronWho : Number -> IntPron = \num -> {
|
||||||
|
s = table {
|
||||||
|
NomP => "who" ;
|
||||||
|
AccP => variants {"who" ; "whom"} ;
|
||||||
|
GenP => "whose" ;
|
||||||
|
GenSP => "whom"
|
||||||
|
} ;
|
||||||
|
n = num
|
||||||
|
} ;
|
||||||
|
|
||||||
|
intPronWhat : Number -> IntPron = \num -> {
|
||||||
|
s = table {
|
||||||
|
GenP => "what's" ;
|
||||||
|
_ => "what"
|
||||||
|
} ;
|
||||||
|
n = num
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Utterances
|
||||||
|
|
||||||
|
-- By utterances we mean whole phrases, such as
|
||||||
|
-- 'can be used as moves in a language game': indicatives, questions, imperative,
|
||||||
|
-- and one-word utterances. The rules are far from complete.
|
||||||
|
--
|
||||||
|
-- N.B. we have not included rules for texts, which we find we cannot say much
|
||||||
|
-- about on this level. In semantically rich GF grammars, texts, dialogues, etc,
|
||||||
|
-- will of course play an important role as categories not reducible to utterances.
|
||||||
|
-- An example is proof texts, whose semantics show a dependence between premises
|
||||||
|
-- and conclusions. Another example is intersentential anaphora.
|
||||||
|
|
||||||
|
Utterance = SS ;
|
||||||
|
|
||||||
|
indicUtt : Sentence -> Utterance = \x -> ss (x.s ++ ".") ;
|
||||||
|
interrogUtt : Question -> Utterance = \x -> ss (x.s ! DirQ ++ "?") ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Questions
|
||||||
|
--
|
||||||
|
-- Questions are either direct ("are you happy") or indirect
|
||||||
|
-- ("if/whether you are happy").
|
||||||
|
|
||||||
|
param
|
||||||
|
QuestForm = DirQ | IndirQ ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
Question = SS1 QuestForm ;
|
||||||
|
|
||||||
|
--3 Yes-no questions
|
||||||
|
--
|
||||||
|
-- Yes-no questions are used both independently
|
||||||
|
-- ("does John walk" / "if John walks")
|
||||||
|
-- and after interrogative adverbials
|
||||||
|
-- ("why does John walk" / "why John walks").
|
||||||
|
--
|
||||||
|
-- It is economical to handle with all these cases by the one
|
||||||
|
-- rule, $questVerbPhrase'$. The word ("ob" / "whether") never appears
|
||||||
|
-- if there is an adverbial.
|
||||||
|
|
||||||
|
questVerbPhrase : NounPhrase -> VerbPhrase -> Question =
|
||||||
|
questVerbPhrase' False ;
|
||||||
|
|
||||||
|
questVerbPhrase' : Bool -> NounPhrase -> VerbPhrase -> Question =
|
||||||
|
\adv,john,walk ->
|
||||||
|
{s = table {
|
||||||
|
DirQ => if_then_else Str walk.isAux
|
||||||
|
(indicVerb (verbOfPhrase walk) john.p john.n ++
|
||||||
|
john.s ! NomP ++ walk.s2 ! john.n)
|
||||||
|
(indicVerb verbP3Do john.p john.n ++
|
||||||
|
john.s ! NomP ++ walk.s ! InfImp ++ walk.s2 ! john.n) ;
|
||||||
|
IndirQ => if_then_else Str adv [] (variants {"if" ; "whether"}) ++
|
||||||
|
(predVerbPhrase john walk).s
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--3 Wh-questions
|
||||||
|
--
|
||||||
|
-- Wh-questions are of two kinds: ones that are like $NP - VP$ sentences,
|
||||||
|
-- others that are line $S/NP - NP$ sentences.
|
||||||
|
|
||||||
|
intVerbPhrase : IntPron -> VerbPhrase -> Question = \who,walk ->
|
||||||
|
{s = \\_ => who.s ! NomP ++ indicVerb (verbOfPhrase walk) P3 who.n ++
|
||||||
|
walk.s2 ! who.n
|
||||||
|
} ;
|
||||||
|
|
||||||
|
intSlash : IntPron -> SentenceSlashNounPhrase -> Question = \who,yousee ->
|
||||||
|
{s = \\q =>
|
||||||
|
let {youSee = case q of {
|
||||||
|
DirQ => yousee.s ! True ;
|
||||||
|
IndirQ => yousee.s ! False
|
||||||
|
}
|
||||||
|
} in
|
||||||
|
variants {
|
||||||
|
who.s ! AccP ++ youSee ++ yousee.s2 ;
|
||||||
|
yousee.s2 ++ who.s ! GenSP ++ youSee
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--3 Interrogative adverbials
|
||||||
|
--
|
||||||
|
-- These adverbials will be defined in the lexicon: they include
|
||||||
|
-- "when", "where", "how", "why", etc, which are all invariant one-word
|
||||||
|
-- expressions. In addition, they can be formed by adding prepositions
|
||||||
|
-- to interrogative pronouns, in the same way as adverbials are formed
|
||||||
|
-- from noun phrases.
|
||||||
|
|
||||||
|
IntAdverb = SS ;
|
||||||
|
|
||||||
|
prepIntAdverb : Preposition -> IntPron -> IntAdverb = \at, whom ->
|
||||||
|
ss (at ++ whom.s ! AccP) ;
|
||||||
|
|
||||||
|
-- A question adverbial can be applied to anything, and whether this makes
|
||||||
|
-- sense is a semantic question.
|
||||||
|
|
||||||
|
questAdverbial : IntAdverb -> NounPhrase -> VerbPhrase -> Question =
|
||||||
|
\why, you, walk ->
|
||||||
|
{s = \\q => why.s ++ (questVerbPhrase' True you walk).s ! q} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Imperatives
|
||||||
|
--
|
||||||
|
-- We only consider second-person imperatives.
|
||||||
|
|
||||||
|
Imperative = SS1 Number ;
|
||||||
|
|
||||||
|
imperVerbPhrase : VerbPhrase -> Imperative = \walk ->
|
||||||
|
{s = \\n => walk.s ! InfImp ++ walk.s2 ! n} ;
|
||||||
|
|
||||||
|
imperUtterance : Number -> Imperative -> Utterance = \n,I ->
|
||||||
|
ss (I.s ! n ++ "!") ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Coordination
|
||||||
|
--
|
||||||
|
-- Coordination is to some extent orthogonal to the rest of syntax, and
|
||||||
|
-- has been treated in a generic way in the module $CO$ in the file
|
||||||
|
-- $coordination.gf$. The overall structure is independent of category,
|
||||||
|
-- but there can be differences in parameter dependencies.
|
||||||
|
--
|
||||||
|
--3 Conjunctions
|
||||||
|
--
|
||||||
|
-- Coordinated phrases are built by using conjunctions, which are either
|
||||||
|
-- simple ("and", "or") or distributed ("both - and", "either - or").
|
||||||
|
--
|
||||||
|
-- The conjunction has an inherent number, which is used when conjoining
|
||||||
|
-- noun phrases: "John and Mary are..." vs. "John or Mary is..."; in the
|
||||||
|
-- case of "or", the result is however plural if any of the disjuncts is.
|
||||||
|
|
||||||
|
Conjunction = CO.Conjunction ** {n : Number} ;
|
||||||
|
ConjunctionDistr = CO.ConjunctionDistr ** {n : Number} ;
|
||||||
|
|
||||||
|
--3 Coordinating sentences
|
||||||
|
--
|
||||||
|
-- We need a category of lists of sentences. It is a discontinuous
|
||||||
|
-- category, the parts corresponding to 'init' and 'last' segments
|
||||||
|
-- (rather than 'head' and 'tail', because we have to keep track of the slot between
|
||||||
|
-- the last two elements of the list). A list has at least two elements.
|
||||||
|
|
||||||
|
ListSentence : Type = SD2 ;
|
||||||
|
|
||||||
|
twoSentence : (_,_ : Sentence) -> ListSentence = CO.twoSS ;
|
||||||
|
|
||||||
|
consSentence : ListSentence -> Sentence -> ListSentence =
|
||||||
|
CO.consSS CO.comma ;
|
||||||
|
|
||||||
|
-- To coordinate a list of sentences by a simple conjunction, we place
|
||||||
|
-- it between the last two elements; commas are put in the other slots,
|
||||||
|
-- e.g. "du rauchst, er trinkt und ich esse".
|
||||||
|
|
||||||
|
conjunctSentence : Conjunction -> ListSentence -> Sentence = \c,xs ->
|
||||||
|
ss (CO.conjunctX c xs) ;
|
||||||
|
|
||||||
|
-- To coordinate a list of sentences by a distributed conjunction, we place
|
||||||
|
-- the first part (e.g. "either") in front of the first element, the second
|
||||||
|
-- part ("or") between the last two elements, and commas in the other slots.
|
||||||
|
-- For sentences this is really not used.
|
||||||
|
|
||||||
|
conjunctDistrSentence : ConjunctionDistr -> ListSentence -> Sentence =
|
||||||
|
\c,xs ->
|
||||||
|
ss (CO.conjunctDistrX c xs) ;
|
||||||
|
|
||||||
|
--3 Coordinating adjective phrases
|
||||||
|
--
|
||||||
|
-- The structure is the same as for sentences. The result is a prefix adjective
|
||||||
|
-- if and only if all elements are prefix.
|
||||||
|
|
||||||
|
ListAdjPhrase : Type = SD2 ** {p : Bool} ;
|
||||||
|
|
||||||
|
twoAdjPhrase : (_,_ : AdjPhrase) -> ListAdjPhrase = \x,y ->
|
||||||
|
CO.twoStr x.s y.s ** {p = andB x.p y.p} ;
|
||||||
|
|
||||||
|
consAdjPhrase : ListAdjPhrase -> AdjPhrase -> ListAdjPhrase = \xs,x ->
|
||||||
|
CO.consStr CO.comma xs x.s ** {p = andB xs.p x.p} ;
|
||||||
|
|
||||||
|
conjunctAdjPhrase : Conjunction -> ListAdjPhrase -> AdjPhrase = \c,xs ->
|
||||||
|
ss (CO.conjunctX c xs) ** {p = xs.p} ;
|
||||||
|
|
||||||
|
conjunctDistrAdjPhrase : ConjunctionDistr -> ListAdjPhrase -> AdjPhrase =
|
||||||
|
\c,xs ->
|
||||||
|
ss (CO.conjunctDistrX c xs) ** {p = xs.p} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Coordinating noun phrases
|
||||||
|
--
|
||||||
|
-- The structure is the same as for sentences. The result is either always plural
|
||||||
|
-- or plural if any of the components is, depending on the conjunction.
|
||||||
|
|
||||||
|
ListNounPhrase : Type = {s1,s2 : NPForm => Str ; n : Number ; p : Person} ;
|
||||||
|
|
||||||
|
twoNounPhrase : (_,_ : NounPhrase) -> ListNounPhrase = \x,y ->
|
||||||
|
CO.twoTable NPForm x y ** {n = conjNumber x.n y.n ; p = conjPerson x.p y.p} ;
|
||||||
|
|
||||||
|
consNounPhrase : ListNounPhrase -> NounPhrase -> ListNounPhrase = \xs,x ->
|
||||||
|
CO.consTable NPForm CO.comma xs x **
|
||||||
|
{n = conjNumber xs.n x.n ; p = conjPerson xs.p x.p} ;
|
||||||
|
|
||||||
|
conjunctNounPhrase : Conjunction -> ListNounPhrase -> NounPhrase = \c,xs ->
|
||||||
|
CO.conjunctTable NPForm c xs ** {n = conjNumber c.n xs.n ; p = xs.p} ;
|
||||||
|
|
||||||
|
conjunctDistrNounPhrase : ConjunctionDistr -> ListNounPhrase -> NounPhrase =
|
||||||
|
\c,xs ->
|
||||||
|
CO.conjunctDistrTable NPForm c xs ** {n = conjNumber c.n xs.n ; p = xs.p} ;
|
||||||
|
|
||||||
|
-- We have to define a calculus of numbers of persons. For numbers,
|
||||||
|
-- it is like the conjunction with $Pl$ corresponding to $False$.
|
||||||
|
|
||||||
|
conjNumber : Number -> Number -> Number = \m,n -> case <m,n> of {
|
||||||
|
<Sg,Sg> => Sg ;
|
||||||
|
_ => Pl
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- For persons, we let the latter argument win ("either you or I am absent"
|
||||||
|
-- but "either I or you are absent"). This is not quite clear.
|
||||||
|
|
||||||
|
conjPerson : Person -> Person -> Person = \_,p ->
|
||||||
|
p ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--2 Subjunction
|
||||||
|
--
|
||||||
|
-- Subjunctions ("when", "if", etc)
|
||||||
|
-- are a different way to combine sentences than conjunctions.
|
||||||
|
-- The main clause can be a sentences, an imperatives, or a question,
|
||||||
|
-- but the subjoined clause must be a sentence.
|
||||||
|
--
|
||||||
|
-- There are uniformly two variant word orders, e.g.
|
||||||
|
-- "if you smoke I get angry"
|
||||||
|
-- and "I get angry if you smoke".
|
||||||
|
|
||||||
|
Subjunction = SS ;
|
||||||
|
|
||||||
|
subjunctSentence : Subjunction -> Sentence -> Sentence -> Sentence =
|
||||||
|
\if, A, B ->
|
||||||
|
ss (subjunctVariants if A.s B.s) ;
|
||||||
|
|
||||||
|
subjunctImperative : Subjunction -> Sentence -> Imperative -> Imperative =
|
||||||
|
\if, A, B ->
|
||||||
|
{s = \\n => subjunctVariants if A.s (B.s ! n)} ;
|
||||||
|
|
||||||
|
subjunctQuestion : Subjunction -> Sentence -> Question -> Question =
|
||||||
|
\if, A, B ->
|
||||||
|
{s = \\q => subjunctVariants if A.s (B.s ! q)} ;
|
||||||
|
|
||||||
|
subjunctVariants : Subjunction -> Str -> Str -> Str = \if,A,B ->
|
||||||
|
variants {if.s ++ A ++ "," ++ B ; B ++ "," ++ if.s ++ A} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 One-word utterances
|
||||||
|
--
|
||||||
|
-- An utterance can consist of one phrase of almost any category,
|
||||||
|
-- the limiting case being one-word utterances. These
|
||||||
|
-- utterances are often (but not always) in what can be called the
|
||||||
|
-- default form of a category, e.g. the nominative.
|
||||||
|
-- This list is far from exhaustive.
|
||||||
|
|
||||||
|
useNounPhrase : NounPhrase -> Utterance = \john ->
|
||||||
|
postfixSS "." (defaultNounPhrase john) ;
|
||||||
|
|
||||||
|
useCommonNounPhrase : Number -> CommNounPhrase -> Utterance = \n,car ->
|
||||||
|
useNounPhrase (indefNounPhrase n car) ;
|
||||||
|
|
||||||
|
useRegularName : SS -> NounPhrase = \john ->
|
||||||
|
nameNounPhrase (nameReg john.s) ;
|
||||||
|
|
||||||
|
-- Here are some default forms.
|
||||||
|
|
||||||
|
defaultNounPhrase : NounPhrase -> SS = \john ->
|
||||||
|
ss (john.s ! NomP) ;
|
||||||
|
|
||||||
|
defaultQuestion : Question -> SS = \whoareyou ->
|
||||||
|
ss (whoareyou.s ! DirQ) ;
|
||||||
|
|
||||||
|
defaultSentence : Sentence -> Utterance = \x ->
|
||||||
|
x ;
|
||||||
|
|
||||||
|
} ;
|
||||||
36
grammars/resource/english/TestEng.gf
Normal file
36
grammars/resource/english/TestEng.gf
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
concrete TestEng of TestAbs = ResEng ** open Syntax in {
|
||||||
|
|
||||||
|
flags startcat=Phr ; lexer=text ; parser=chart ; unlexer=text ;
|
||||||
|
|
||||||
|
-- a random sample from the lexicon
|
||||||
|
|
||||||
|
lin
|
||||||
|
Big = mkAdjDegr "big" "bigger" "biggest";
|
||||||
|
Small = adjDegrReg "small" ;
|
||||||
|
Old = adjDegrReg "old" ;
|
||||||
|
Young = adjDegrReg "young" ;
|
||||||
|
Man = cnHum (mkNoun "man" "men" "man's" "men's") ;
|
||||||
|
Woman = cnHum (mkNoun "woman" "women" "woman's" "women's") ;
|
||||||
|
Car = cnNoHum (nounReg "car") ;
|
||||||
|
House = cnNoHum (nounReg "house") ;
|
||||||
|
Light = cnNoHum (nounReg "light") ;
|
||||||
|
Walk = verbNoPart (regVerbP3 "walk") ;
|
||||||
|
Run = verbNoPart (regVerbP3 "run") ;
|
||||||
|
Say = verbNoPart (regVerbP3 "say") ;
|
||||||
|
Prove = verbNoPart (regVerbP3 "prove") ;
|
||||||
|
Send = mkTransVerbDir (regVerbP3 "send") ;
|
||||||
|
Love = mkTransVerbDir (regVerbP3 "love") ;
|
||||||
|
Wait = mkTransVerb (regVerbP3 "wait") "for" ;
|
||||||
|
Mother = funOfReg "mother" Hum ;
|
||||||
|
Uncle = funOfReg "uncle" Hum ;
|
||||||
|
|
||||||
|
Always = advPre "always" ;
|
||||||
|
Well = advPost "well" ;
|
||||||
|
|
||||||
|
SwitchOn = mkTransVerbPart (verbP3s "switch") "on" ;
|
||||||
|
SwitchOff = mkTransVerbPart (verbP3s "switch") "off" ;
|
||||||
|
|
||||||
|
John = nameReg "John" ;
|
||||||
|
Mary = nameReg "Mary" ;
|
||||||
|
|
||||||
|
} ;
|
||||||
101
grammars/resource/english/Types.gf
Normal file
101
grammars/resource/english/Types.gf
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
--1 English Word Classes and Morphological Parameters
|
||||||
|
--
|
||||||
|
-- This is a resource module for English morphology, defining the
|
||||||
|
-- morphological parameters and word classes of English. It is aimed
|
||||||
|
-- to be complete w.r.t. the description of word forms.
|
||||||
|
-- However, it only includes those parameters that are needed for
|
||||||
|
-- analysing individual words: such parameters are defined in syntax modules.
|
||||||
|
--
|
||||||
|
-- we use the language-independent prelude.
|
||||||
|
|
||||||
|
resource Types = open Prelude in {
|
||||||
|
|
||||||
|
--
|
||||||
|
--2 Enumerated parameter types
|
||||||
|
--
|
||||||
|
-- These types are the ones found in school grammars.
|
||||||
|
-- Their parameter values are atomic.
|
||||||
|
|
||||||
|
param
|
||||||
|
Number = Sg | Pl ;
|
||||||
|
Gender = NoHum | Hum ;
|
||||||
|
Case = Nom | Gen ;
|
||||||
|
Person = P1 | P2 | P3 ;
|
||||||
|
Degree = Pos | Comp | Sup ;
|
||||||
|
|
||||||
|
-- For data abstraction, we define
|
||||||
|
|
||||||
|
oper
|
||||||
|
singular = Sg ;
|
||||||
|
plural = Pl ;
|
||||||
|
|
||||||
|
--2 Word classes and hierarchical parameter types
|
||||||
|
--
|
||||||
|
-- Real parameter types (i.e. ones on which words and phrases depend)
|
||||||
|
-- are often hierarchical. The alternative would be cross-products of
|
||||||
|
-- simple parameters, but this would usually overgenerate.
|
||||||
|
--
|
||||||
|
|
||||||
|
--3 Common nouns
|
||||||
|
--
|
||||||
|
-- Common nouns are inflected in number and case.
|
||||||
|
|
||||||
|
CommonNoun : Type = {s : Number => Case => Str} ;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
--3 Adjectives
|
||||||
|
--
|
||||||
|
-- The major division is between the comparison degrees, but it
|
||||||
|
-- is also good to leave room for adjectives that cannon be compared.
|
||||||
|
-- Such adjectives are simply strings.
|
||||||
|
|
||||||
|
Adjective : Type = SS ;
|
||||||
|
AdjDegr = SS1 Degree ;
|
||||||
|
|
||||||
|
--3 Verbs
|
||||||
|
--
|
||||||
|
-- We limit the grammar so far to verbs in infinitive-imperative or present tense.
|
||||||
|
-- The present tense is made to depend on person, which correspond to forms
|
||||||
|
-- in the singular; plural forms are uniformly equal to the 2nd person singular.
|
||||||
|
|
||||||
|
param
|
||||||
|
VForm = InfImp | Indic Person ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
VerbP3 : Type = SS1 VForm ;
|
||||||
|
|
||||||
|
-- A full verb can moreover have a particle.
|
||||||
|
|
||||||
|
Particle : Type = Str ;
|
||||||
|
Verb = VerbP3 ** {s1 : Particle} ;
|
||||||
|
|
||||||
|
--
|
||||||
|
--3 Pronouns
|
||||||
|
--
|
||||||
|
-- For pronouns, we need four case forms: "I" - "me" - "my" - "mine".
|
||||||
|
|
||||||
|
param
|
||||||
|
NPForm = NomP | AccP | GenP | GenSP ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
Pronoun : Type = {s : NPForm => Str ; n : Number ; p : Person} ;
|
||||||
|
|
||||||
|
-- Coercions between pronoun cases and ordinaty cases.
|
||||||
|
|
||||||
|
toCase : NPForm -> Case = \c -> case c of {GenP => Gen ; _ => Nom} ;
|
||||||
|
toNPForm : Case -> NPForm = \c -> case c of {Gen => GenP ; _ => NomP} ; ---
|
||||||
|
|
||||||
|
--3 Proper names
|
||||||
|
--
|
||||||
|
-- Proper names only need two cases.
|
||||||
|
|
||||||
|
ProperName : Type = SS1 Case ;
|
||||||
|
|
||||||
|
--3 Relative pronouns
|
||||||
|
--
|
||||||
|
-- Relative pronouns are inflected in gender (human/nonhuman), number, and case.
|
||||||
|
|
||||||
|
RelPron : Type = {s : Gender => Number => NPForm => Str} ;
|
||||||
|
} ;
|
||||||
|
|
||||||
52
grammars/resource/german/DatabaseDeu.gf
Normal file
52
grammars/resource/german/DatabaseDeu.gf
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
concrete DatabaseDeu of Database =
|
||||||
|
open Prelude,Syntax,Deutsch,Predication,Paradigms,DatabaseRes in {
|
||||||
|
|
||||||
|
flags lexer=text ; unlexer=text ;
|
||||||
|
|
||||||
|
lincat
|
||||||
|
Phras = SS1 Bool ; -- long or short form
|
||||||
|
Subject = NP ;
|
||||||
|
Noun = CN ;
|
||||||
|
Property = AP ;
|
||||||
|
Comparison = AdjDeg ;
|
||||||
|
Relation = Adj2 ;
|
||||||
|
Feature = Fun ;
|
||||||
|
Value = NP ;
|
||||||
|
Name = ProperName ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
LongForm sent = ss (sent.s ! True ++ "?") ;
|
||||||
|
ShortForm sent = ss (sent.s ! False ++ "?") ;
|
||||||
|
|
||||||
|
WhichAre A B = mkSent (defaultQuestion (IntVP (NounIPMany A) (PosA B)))
|
||||||
|
(defaultNounPhrase (IndefManyNP (ModAdj B A))) ;
|
||||||
|
|
||||||
|
IsIt Q A = mkSentSame (defaultQuestion (QuestVP Q (PosA A))) ;
|
||||||
|
|
||||||
|
MoreThan = ComparAdjP ;
|
||||||
|
TheMost = SuperlNP ;
|
||||||
|
Relatively C _ = PositAdjP C ;
|
||||||
|
|
||||||
|
RelatedTo = ComplAdj ;
|
||||||
|
|
||||||
|
FeatureOf = appFun1 ;
|
||||||
|
ValueOf F V = appFun1 F (UsePN V) ;
|
||||||
|
|
||||||
|
WithProperty A B = ModAdj B A ;
|
||||||
|
|
||||||
|
Individual = nameNounPhrase ;
|
||||||
|
|
||||||
|
AllN = DetNP AllDet ;
|
||||||
|
MostN = DetNP MostDet ;
|
||||||
|
EveryN = DetNP EveryDet ;
|
||||||
|
|
||||||
|
-- only these are language-dependent
|
||||||
|
|
||||||
|
Any = detNounPhrase einDet ;
|
||||||
|
|
||||||
|
IsThere A = mkSentPrel ["gibt es"] (defaultNounPhrase (IndefOneNP A)) ;
|
||||||
|
AreThere A = mkSentPrel ["gibt es"] (defaultNounPhrase (IndefManyNP A)) ;
|
||||||
|
|
||||||
|
WhatIs V = mkSentPrel ["was ist"] (defaultNounPhrase V) ;
|
||||||
|
|
||||||
|
} ;
|
||||||
11
grammars/resource/german/DatabaseRes.gf
Normal file
11
grammars/resource/german/DatabaseRes.gf
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
resource DatabaseRes = open Prelude in {
|
||||||
|
oper
|
||||||
|
mkSent : SS -> SS -> SS1 Bool = \long, short ->
|
||||||
|
{s = table {b => if_then_else Str b long.s short.s}} ;
|
||||||
|
|
||||||
|
mkSentPrel : Str -> SS -> SS1 Bool = \prel, matter ->
|
||||||
|
mkSent (ss (prel ++ matter.s)) matter ;
|
||||||
|
|
||||||
|
mkSentSame : SS -> SS1 Bool = \s ->
|
||||||
|
mkSent s s ;
|
||||||
|
} ;
|
||||||
1
grammars/resource/german/Deutsch.gf
Normal file
1
grammars/resource/german/Deutsch.gf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resource Deutsch = reuse ResDeu ;
|
||||||
23
grammars/resource/german/Logical.gf
Normal file
23
grammars/resource/german/Logical.gf
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-- Slightly ad hoc and formal negation and connectives.
|
||||||
|
|
||||||
|
resource Logical = Predication ** open Deutsch, Paradigms in {
|
||||||
|
|
||||||
|
oper
|
||||||
|
negS : S -> S ; -- es ist nicht der Fall, dass S
|
||||||
|
univS : CN -> S -> S ; -- für alle CNs gilt es, dass S
|
||||||
|
existS : CN -> S -> S ; -- es gibt ein CN derart, dass S
|
||||||
|
existManyS : CN -> S -> S ; -- es gibt CNs derart, dass S
|
||||||
|
--.
|
||||||
|
|
||||||
|
negS = \A ->
|
||||||
|
PredVP ItNP (NegNP (DefOneNP (CNthatS (UseN (nRaum "Fall" "Fälle")) A))) ;
|
||||||
|
univS = \A,B ->
|
||||||
|
PredVP ItNP (AdvVP (PosVS (mkV "gelten" "gilt" "gelte" "gegolten") B)
|
||||||
|
(mkPP accusative "für" (DetNP AllDet A))) ;
|
||||||
|
existS = \A,B ->
|
||||||
|
PredVP ItNP (PosTV (tvDir (mkV "geben" "gibt" "gib" "gegeben"))
|
||||||
|
(IndefOneNP (ModRC A (RelSuch B)))) ;
|
||||||
|
existManyS = \A,B ->
|
||||||
|
PredVP ItNP (PosTV (tvDir (mkV "geben" "gibt" "gib" "gegeben"))
|
||||||
|
(IndefManyNP (ModRC A (RelSuch B)))) ;
|
||||||
|
} ;
|
||||||
399
grammars/resource/german/Morpho.gf
Normal file
399
grammars/resource/german/Morpho.gf
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
--1 A Simple German Resource Morphology
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002
|
||||||
|
--
|
||||||
|
-- This resource morphology contains definitions needed in the resource
|
||||||
|
-- syntax. It moreover contains the most usual inflectional patterns.
|
||||||
|
--
|
||||||
|
-- We use the parameter types and word classes defined in $types.Deu.gf$.
|
||||||
|
|
||||||
|
resource Morpho = Types ** open (Predef=Predef), Prelude in {
|
||||||
|
|
||||||
|
--2 Nouns
|
||||||
|
--
|
||||||
|
-- For conciseness and abstraction, we define a method for
|
||||||
|
-- generating a case-dependent table from a list of four forms.
|
||||||
|
|
||||||
|
oper
|
||||||
|
caselist : (_,_,_,_ : Str) -> Case => Str = \n,a,d,g -> table {
|
||||||
|
Nom => n ; Acc => a ; Dat => d ; Gen => g} ;
|
||||||
|
|
||||||
|
-- The *worst-case macro* for common nouns needs six forms: all plural forms
|
||||||
|
-- are always the same except for the dative.
|
||||||
|
|
||||||
|
mkNoun : (_,_,_,_,_,_ : Str) -> Gender -> CommNoun =
|
||||||
|
\mann, mannen, manne, mannes, männer, männern, g -> {s = table {
|
||||||
|
Sg => caselist mann mannen manne mannes ;
|
||||||
|
Pl => caselist männer männer männern männer
|
||||||
|
} ; g = g} ;
|
||||||
|
|
||||||
|
-- But we never need all the six forms at the same time. Often
|
||||||
|
-- we need just two, three, or four forms.
|
||||||
|
|
||||||
|
mkNoun4 : (_,_,_,_ : Str) -> Gender -> CommNoun = \kuh,kuhes,kühe,kühen ->
|
||||||
|
mkNoun kuh kuh kuh kuhes kühe kühen ;
|
||||||
|
|
||||||
|
mkNoun3 : (_,_,_ : Str) -> Gender -> CommNoun = \kuh,kühe,kühen ->
|
||||||
|
mkNoun kuh kuh kuh kuh kühe kühen ;
|
||||||
|
|
||||||
|
mkNoun2n : (_,_ : Str) -> Gender -> CommNoun = \zahl, zahlen ->
|
||||||
|
mkNoun3 zahl zahlen zahlen ;
|
||||||
|
|
||||||
|
mkNoun2es : (_,_ : Str) -> Gender -> CommNoun = \wort, wörter ->
|
||||||
|
mkNoun wort wort wort (wort + "es") wörter (wörter + "n") ;
|
||||||
|
|
||||||
|
mkNoun2s : (_,_ : Str) -> Gender -> CommNoun = \vater, väter ->
|
||||||
|
mkNoun vater vater vater (vater + "s") väter (väter + "n") ;
|
||||||
|
|
||||||
|
mkNoun2ses : (_,_ : Str) -> Gender -> CommNoun = \wort,wörter ->
|
||||||
|
mkNoun wort wort wort (wort + variants {"es" ; "s"}) wörter (wörter + "n") ;
|
||||||
|
|
||||||
|
-- Here are the school grammar declensions with their commonest variations.
|
||||||
|
-- Unfortunately we cannot define *Umlaut* in GF, but have to give two forms.
|
||||||
|
--
|
||||||
|
-- First declension, with plural "en"/"n", including weak masculins:
|
||||||
|
|
||||||
|
declN1 : Str -> CommNoun = \zahl ->
|
||||||
|
mkNoun2n zahl (zahl + "en") Fem ;
|
||||||
|
|
||||||
|
declN1e : Str -> CommNoun = \stufe ->
|
||||||
|
mkNoun2n stufe (stufe + "n") Fem ;
|
||||||
|
|
||||||
|
declN1M : Str -> CommNoun = \junge -> let {jungen = junge + "n"} in
|
||||||
|
mkNoun junge jungen jungen jungen jungen jungen Masc ;
|
||||||
|
|
||||||
|
declN1eM : Str -> CommNoun = \soldat -> let {soldaten = soldat + "en"} in
|
||||||
|
mkNoun soldat soldaten soldaten soldaten soldaten soldaten Masc ;
|
||||||
|
|
||||||
|
-- Second declension, with plural "e":
|
||||||
|
|
||||||
|
declN2 : Str -> CommNoun = \punkt ->
|
||||||
|
mkNoun2es punkt (punkt+"e") Masc ;
|
||||||
|
|
||||||
|
declN2i : Str -> CommNoun = \onkel ->
|
||||||
|
mkNoun2s onkel onkel Masc ;
|
||||||
|
|
||||||
|
declN2u : (_,_ : Str) -> CommNoun = \raum,räume ->
|
||||||
|
mkNoun2es raum räume Masc ;
|
||||||
|
|
||||||
|
declN2uF : (_,_ : Str) -> CommNoun = \kuh,kühe ->
|
||||||
|
mkNoun3 kuh kühe (kühe + "n") Fem ;
|
||||||
|
|
||||||
|
-- Third declension, with plural "er":
|
||||||
|
|
||||||
|
declN3 : Str -> CommNoun = \punkt ->
|
||||||
|
mkNoun2es punkt (punkt+"er") Neut ;
|
||||||
|
|
||||||
|
declN3u : (_,_ : Str) -> CommNoun = \buch,bücher ->
|
||||||
|
mkNoun2ses buch bücher Neut ;
|
||||||
|
|
||||||
|
declN3uS : (_,_ : Str) -> CommNoun = \haus,häuser ->
|
||||||
|
mkNoun2es haus häuser Neut ;
|
||||||
|
|
||||||
|
-- Plural with "s":
|
||||||
|
|
||||||
|
declNs : Str -> CommNoun = \restaurant ->
|
||||||
|
mkNoun3 restaurant (restaurant+"s") (restaurant+"s") Neut ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Pronouns
|
||||||
|
--
|
||||||
|
-- Here we define personal and relative pronouns.
|
||||||
|
-- All personal pronouns, except "ihr", conform to the simple
|
||||||
|
-- pattern $mkPronPers$.
|
||||||
|
|
||||||
|
ProPN = {s : NPForm => Str ; n : Number ; p : Person} ;
|
||||||
|
|
||||||
|
mkPronPers : (_,_,_,_,_ : Str) -> Number -> Person -> ProPN =
|
||||||
|
\ich,mich,mir,meines,mein,n,p -> {
|
||||||
|
s = table {
|
||||||
|
NPCase c => caselist ich mich mir meines ! c ;
|
||||||
|
NPPoss gn c => mein + pronEnding ! gn ! c
|
||||||
|
} ;
|
||||||
|
n = n ;
|
||||||
|
p = p
|
||||||
|
} ;
|
||||||
|
|
||||||
|
pronEnding : GenNum => Case => Str = table {
|
||||||
|
GSg Masc => caselist "" "en" "em" "es" ;
|
||||||
|
GSg Fem => caselist "e" "e" "er" "er" ;
|
||||||
|
GSg Neut => caselist "" "" "em" "es" ;
|
||||||
|
GPl => caselist "e" "e" "en" "er"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
pronIch = mkPronPers "ich" "mich" "mir" "meines" "mein" Sg P1 ;
|
||||||
|
pronDu = mkPronPers "du" "dich" "dir" "deines" "dein" Sg P2 ;
|
||||||
|
pronEr = mkPronPers "er" "ihn" "ihm" "seines" "sein" Sg P3 ;
|
||||||
|
pronSie = mkPronPers "sie" "sie" "ihr" "ihres" "ihr" Sg P3 ;
|
||||||
|
pronEs = mkPronPers "es" "es" "ihm" "seines" "sein" Sg P3 ;
|
||||||
|
pronWir = mkPronPers "wir" "uns" "uns" "unser" "unser" Pl P1 ;
|
||||||
|
|
||||||
|
pronSiePl = mkPronPers "sie" "sie" "ihnen" "ihrer" "ihr" Pl P3 ;
|
||||||
|
pronSSie = mkPronPers "Sie" "Sie" "Ihnen" "Ihrer" "Ihr" Pl P3 ; ---
|
||||||
|
|
||||||
|
-- We still have wrong agreement with the complement of the polite "Sie":
|
||||||
|
-- it is in plural, like the verb, although it should be in singular.
|
||||||
|
|
||||||
|
-- The peculiarity with "ihr" is the presence of "e" in forms without an ending.
|
||||||
|
|
||||||
|
pronIhr =
|
||||||
|
{s = table {
|
||||||
|
NPPoss (GSg Masc) Nom => "euer" ;
|
||||||
|
NPPoss (GSg Neut) Nom => "euer" ;
|
||||||
|
NPPoss (GSg Neut) Acc => "euer" ;
|
||||||
|
pf => (mkPronPers "ihr" "euch" "euch" "euer" "eur" Pl P2).s ! pf
|
||||||
|
} ;
|
||||||
|
n = Pl ;
|
||||||
|
p = P2
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Relative pronouns are like the definite article, except in the genitive and
|
||||||
|
-- the plural dative. The function $artDef$ will be defined right below.
|
||||||
|
|
||||||
|
RelPron : Type = {s : GenNum => Case => Str} ;
|
||||||
|
|
||||||
|
relPron : RelPron = {s = \\gn,c =>
|
||||||
|
case <gn,c> of {
|
||||||
|
<GSg Fem,Gen> => "deren" ;
|
||||||
|
<GSg g,Gen> => "dessen" ;
|
||||||
|
<GPl,Dat> => "denen" ;
|
||||||
|
<GPl,Gen> => "deren" ;
|
||||||
|
_ => artDef ! gn ! c
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Articles
|
||||||
|
--
|
||||||
|
-- Here are all forms the indefinite and definite article.
|
||||||
|
-- The indefinite article is like a large class of pronouns.
|
||||||
|
-- The definite article is more peculiar; we don't try to
|
||||||
|
-- subsume it to any general rule.
|
||||||
|
|
||||||
|
artIndef : Gender => Case => Str = \\g,c => "ein" + pronEnding ! GSg g ! c ;
|
||||||
|
|
||||||
|
artDef : GenNum => Case => Str = table {
|
||||||
|
GSg Masc => caselist "der" "den" "dem" "des" ;
|
||||||
|
GSg Fem => caselist "die" "die" "der" "der" ;
|
||||||
|
GSg Neut => caselist "das" "das" "dem" "des" ;
|
||||||
|
GPl => caselist "die" "die" "den" "der"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Adjectives
|
||||||
|
--
|
||||||
|
-- As explained in $types.Deu.gf$, it
|
||||||
|
-- would be superfluous to use the cross product of gender and number,
|
||||||
|
-- since there is no gender distinction in the plural. But it is handy to have
|
||||||
|
-- a function that constructs gender-number complexes.
|
||||||
|
|
||||||
|
gNumber : Gender -> Number -> GenNum = \g,n ->
|
||||||
|
case n of {
|
||||||
|
Sg => GSg g ;
|
||||||
|
Pl => GPl
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- It's also handy to have a function that finds out the number from such a complex.
|
||||||
|
|
||||||
|
numGenNum : GenNum -> Number = \gn ->
|
||||||
|
case gn of {
|
||||||
|
GSg _ => Sg ;
|
||||||
|
GPl => Pl
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- This function costructs parameters in the complex type of adjective forms.
|
||||||
|
|
||||||
|
aMod : Adjf -> Gender -> Number -> Case -> AForm = \a,g,n,c ->
|
||||||
|
AMod a (gNumber g n) c ;
|
||||||
|
|
||||||
|
-- The worst-case macro for adjectives (positive degree) only needs
|
||||||
|
-- two forms.
|
||||||
|
|
||||||
|
mkAdjective : (_,_ : Str) -> Adjective = \böse,bös -> {s = table {
|
||||||
|
APred => böse ;
|
||||||
|
AMod Strong (GSg Masc) c =>
|
||||||
|
caselist (bös+"er") (bös+"en") (bös+"em") (bös+"es") ! c ;
|
||||||
|
AMod Strong (GSg Fem) c =>
|
||||||
|
caselist (bös+"e") (bös+"e") (bös+"er") (bös+"er") ! c ;
|
||||||
|
AMod Strong (GSg Neut) c =>
|
||||||
|
caselist (bös+"es") (bös+"es") (bös+"em") (bös+"es") ! c ;
|
||||||
|
AMod Strong GPl c =>
|
||||||
|
caselist (bös+"e") (bös+"e") (bös+"en") (bös+"er") ! c ;
|
||||||
|
AMod Weak (GSg g) c => case <g,c> of {
|
||||||
|
<_,Nom> => bös+"e" ;
|
||||||
|
<Masc,Acc> => bös+"en" ;
|
||||||
|
<_,Acc> => bös+"e" ;
|
||||||
|
_ => bös+"en" } ;
|
||||||
|
AMod Weak GPl c => bös+"en"
|
||||||
|
}} ;
|
||||||
|
|
||||||
|
-- Here are some classes of adjectives:
|
||||||
|
|
||||||
|
adjReg : Str -> Adjective = \gut -> mkAdjective gut gut ;
|
||||||
|
adjE : Str -> Adjective = \bös -> mkAdjective (bös+"e") bös ;
|
||||||
|
adjEr : Str -> Adjective = \teu -> mkAdjective (teu+"er") (teu+"r") ;
|
||||||
|
adjInvar : Str -> Adjective = \prima -> {s = table {_ => prima}} ;
|
||||||
|
|
||||||
|
-- The first three classes can be recognized from the end of the word, depending
|
||||||
|
-- on if it is "e", "er", or something else.
|
||||||
|
|
||||||
|
adjGen : Str -> Adjective = \gut -> let {
|
||||||
|
er = Predef.dp 2 gut ;
|
||||||
|
teu = Predef.tk 2 gut ;
|
||||||
|
e = Predef.dp 1 gut ;
|
||||||
|
bös = Predef.tk 1 gut
|
||||||
|
} in
|
||||||
|
ifTok Adjective er "er" (adjEr teu) (
|
||||||
|
ifTok Adjective e "e" (adjE bös) (
|
||||||
|
(adjReg gut))) ;
|
||||||
|
|
||||||
|
|
||||||
|
-- The comparison of adjectives needs three adjectives in the worst case.
|
||||||
|
|
||||||
|
mkAdjComp : (_,_,_ : Adjective) -> AdjComp = \gut,besser,best ->
|
||||||
|
{s = table {Pos => gut.s ; Comp => besser.s ; Sup => best.s}} ;
|
||||||
|
|
||||||
|
-- It can be done by just three strings, if each of the comparison
|
||||||
|
-- forms taken separately is a regular adjective.
|
||||||
|
|
||||||
|
adjCompReg3 : (_,_,_ : Str) -> AdjComp = \gut,besser,best ->
|
||||||
|
mkAdjComp (adjReg gut) (adjReg besser) (adjReg best) ;
|
||||||
|
|
||||||
|
-- If also the comparison forms are regular, one string is enough.
|
||||||
|
|
||||||
|
adjCompReg : Str -> AdjComp = \billig ->
|
||||||
|
adjCompReg3 billig (billig+"er") (billig+"st") ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Verbs
|
||||||
|
--
|
||||||
|
-- We limit ourselves to verbs in present tense infinitive, indicative,
|
||||||
|
-- and imperative, and past participle. Other forms will be introduced later.
|
||||||
|
--
|
||||||
|
-- The worst-case macro needs three forms: the infinitive, the third person
|
||||||
|
-- singular indicative, and the second person singular imperative.
|
||||||
|
-- We take care of the special cases "ten", "sen", "ln", "rn".
|
||||||
|
--
|
||||||
|
-- A famous law about Germanic languages says that plural first and third person
|
||||||
|
-- are similar.
|
||||||
|
|
||||||
|
mkVerbum : (_,_,_,_ : Str) -> Verbum = \geben, gib, gb, gegeben ->
|
||||||
|
let {
|
||||||
|
en = Predef.dp 2 geben ;
|
||||||
|
geb = ifTok Tok (Predef.tk 1 en) "e" (Predef.tk 2 geben)(Predef.tk 1 geben) ;
|
||||||
|
gebt = ifTok Tok (Predef.dp 1 geb) "t" (geb + "et") (geb + "t") ;
|
||||||
|
gibst = ifTok Tok (Predef.dp 1 gib) "s" (gib + "t") (gib + "st") ;
|
||||||
|
gegebener = (adjReg gegeben).s
|
||||||
|
} in table {
|
||||||
|
VInf => geben ;
|
||||||
|
VInd Sg P1 => geb + "e" ;
|
||||||
|
VInd Sg P2 => gibst ;
|
||||||
|
VInd Sg P3 => gib + "t" ;
|
||||||
|
VInd Pl P2 => gebt ;
|
||||||
|
VInd Pl _ => geben ; -- the famous law
|
||||||
|
VImp Sg => gb ;
|
||||||
|
VImp Pl => gebt ;
|
||||||
|
VPart a => gegebener ! a
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Regular verbs:
|
||||||
|
|
||||||
|
regVerb : Str -> Verbum = \legen ->
|
||||||
|
let {lege = ifTok Tok (Predef.dp 3 legen) "ten" (Predef.tk 1 legen) (
|
||||||
|
ifTok Tok (Predef.dp 2 legen) "en" (Predef.tk 2 legen) (
|
||||||
|
Predef.tk 1 legen))} in
|
||||||
|
mkVerbum legen lege lege ("ge" + (lege + "t")) ;
|
||||||
|
|
||||||
|
-- Verbs ending with "t"; now recognized in $mkVerbum$.
|
||||||
|
|
||||||
|
verbWarten : Str -> Verbum = regVerb ;
|
||||||
|
|
||||||
|
-- Verbs with Umlaut in the second and third person singular and imperative:
|
||||||
|
|
||||||
|
verbSehen : Str -> Str -> Str -> Verbum = \sehen, sieht, gesehen ->
|
||||||
|
let {sieh = Predef.tk 1 sieht} in mkVerbum sehen sieh sieh gesehen ;
|
||||||
|
|
||||||
|
-- Verbs with Umlaut in the second and third person singular but not imperative:
|
||||||
|
|
||||||
|
verbLaufen : Str -> Str -> Str -> Verbum = \laufen, läuft, gelaufen ->
|
||||||
|
let {läuf = Predef.tk 1 läuft ; laufe = Predef.tk 1 laufen}
|
||||||
|
in mkVerbum laufen läuf laufe gelaufen ;
|
||||||
|
|
||||||
|
-- The verb "be":
|
||||||
|
|
||||||
|
verbumSein : Verbum = let {
|
||||||
|
gewesen = (adjReg "gewesen").s
|
||||||
|
} in
|
||||||
|
table {
|
||||||
|
VInf => "sein" ;
|
||||||
|
VInd Sg P1 => "bin" ;
|
||||||
|
VInd Sg P2 => "bist" ;
|
||||||
|
VInd Sg P3 => "ist" ;
|
||||||
|
VInd Pl P2 => "seid" ;
|
||||||
|
VInd Pl _ => "sind" ;
|
||||||
|
VImp Sg => "sei" ;
|
||||||
|
VImp Pl => "seiet" ;
|
||||||
|
VPart a => gewesen ! a
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- The verb "have":
|
||||||
|
|
||||||
|
verbumHaben : Verbum = let {
|
||||||
|
haben = (regVerb "haben")
|
||||||
|
} in
|
||||||
|
table {
|
||||||
|
VInd Sg P2 => "hast" ;
|
||||||
|
VInd Sg P3 => "hat" ;
|
||||||
|
v => haben ! v
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- The verb "become", used as the passive auxiliary:
|
||||||
|
|
||||||
|
verbumWerden : Verbum = let {
|
||||||
|
werden = regVerb "werden" ;
|
||||||
|
geworden = (adjReg "geworden").s
|
||||||
|
} in
|
||||||
|
table {
|
||||||
|
VInd Sg P2 => "wirst" ;
|
||||||
|
VInd Sg P3 => "wird" ;
|
||||||
|
VPart a => geworden ! a ;
|
||||||
|
v => werden ! v
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- A *full verb* ($Verb$) consists of the inflection forms ($Verbum$) and
|
||||||
|
-- a *particle* (e.g. "aus-sehen"). Simple verbs are the ones that have no
|
||||||
|
-- such particle.
|
||||||
|
|
||||||
|
mkVerb : Verbum -> Particle -> Verb = \v,p -> {s = v ; s2 = p} ;
|
||||||
|
|
||||||
|
mkVerbSimple : Verbum -> Verb = \v -> mkVerb v [] ;
|
||||||
|
|
||||||
|
verbSein = mkVerbSimple verbumSein ;
|
||||||
|
verbHaben = mkVerbSimple verbumHaben ;
|
||||||
|
verbWerden = mkVerbSimple verbumWerden ;
|
||||||
|
|
||||||
|
{-
|
||||||
|
-- tests for optimizer
|
||||||
|
verbumSein2 : Verbum =
|
||||||
|
table {
|
||||||
|
VInf => "sein" ;
|
||||||
|
VInd Sg P1 => "bin" ;
|
||||||
|
VInd Sg P2 => "bist" ;
|
||||||
|
VInd Sg P3 => "ist" ;
|
||||||
|
VInd Pl P2 => "seid" ;
|
||||||
|
VInd Pl _ => "sind" ;
|
||||||
|
VImp Sg => "sei" ;
|
||||||
|
VImp Pl => "seiet" ;
|
||||||
|
VPart a => (adjReg "gewesen").s ! a
|
||||||
|
} ;
|
||||||
|
|
||||||
|
verbumHaben2 : Verbum =
|
||||||
|
table {
|
||||||
|
VInd Sg P2 => "hast" ;
|
||||||
|
VInd Sg P3 => "hat" ;
|
||||||
|
v => regVerb "haben" ! v
|
||||||
|
} ;
|
||||||
|
-}
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
300
grammars/resource/german/Paradigms.gf
Normal file
300
grammars/resource/german/Paradigms.gf
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
--1 German Lexical Paradigms
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2003
|
||||||
|
--
|
||||||
|
-- This is an API to the user of the resource grammar
|
||||||
|
-- for adding lexical items. It give shortcuts for forming
|
||||||
|
-- expressions of basic categories: nouns, adjectives, verbs.
|
||||||
|
--
|
||||||
|
-- Closed categories (determiners, pronouns, conjunctions) are
|
||||||
|
-- accessed through the resource syntax API, $resource.Abs.gf$.
|
||||||
|
--
|
||||||
|
-- The main difference with $morpho.Deu.gf$ is that the types
|
||||||
|
-- referred to are compiled resource grammar types. We have moreover
|
||||||
|
-- had the design principle of always having existing forms as string
|
||||||
|
-- arguments of the paradigms, not stems.
|
||||||
|
--
|
||||||
|
-- The following modules are presupposed:
|
||||||
|
|
||||||
|
resource Paradigms = open (Predef=Predef), Prelude, (Morpho=Morpho), Syntax, Deutsch in {
|
||||||
|
|
||||||
|
|
||||||
|
--2 Parameters
|
||||||
|
--
|
||||||
|
-- To abstract over gender names, we define the following identifiers.
|
||||||
|
|
||||||
|
oper
|
||||||
|
masculine : Gender ;
|
||||||
|
feminine : Gender ;
|
||||||
|
neuter : Gender ;
|
||||||
|
|
||||||
|
-- To abstract over case names, we define the following.
|
||||||
|
|
||||||
|
nominative : Case ;
|
||||||
|
accusative : Case ;
|
||||||
|
dative : Case ;
|
||||||
|
genitive : Case ;
|
||||||
|
|
||||||
|
-- To abstract over number names, we define the following.
|
||||||
|
|
||||||
|
singular : Number ;
|
||||||
|
plural : Number ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Nouns
|
||||||
|
|
||||||
|
-- Worst case: give all four singular forms, two plural forms (others + dative),
|
||||||
|
-- and the gender.
|
||||||
|
|
||||||
|
mkN : (_,_,_,_,_,_ : Str) -> Gender -> N ;
|
||||||
|
-- mann, mann, manne, mannes, männer, männern
|
||||||
|
|
||||||
|
-- Often it is enough with singular and plural nominatives, and singular
|
||||||
|
-- genitive. The plural dative
|
||||||
|
-- is computed by the heuristic that it is the same as the nominative this
|
||||||
|
-- ends with "n" or "s", otherwise "n" is added.
|
||||||
|
|
||||||
|
nGen : Str -> Str -> Str -> Gender -> N ; -- punkt,punktes,punkt
|
||||||
|
|
||||||
|
-- Here are some common patterns. Singular nominative or two nominatives are needed.
|
||||||
|
-- Two forms are needed in case of Umlaut, which would be complicated to define.
|
||||||
|
-- For the same reason, we have separate patterns for multisyllable stems.
|
||||||
|
--
|
||||||
|
-- The weak masculine pattern $nSoldat$ avoids duplicating the final "e".
|
||||||
|
|
||||||
|
nRaum : (_,_ : Str) -> N ; -- Raum, (Raumes,) Räume (masc)
|
||||||
|
nTisch : Str -> N ; -- Tisch, (Tisches, Tische) (masc)
|
||||||
|
nVater : (_,_ : Str) -> N ; -- Vater, (Vaters,) Väter (masc)
|
||||||
|
nFehler : Str -> N ; -- Fehler, (fehlers, Fehler) (masc)
|
||||||
|
nSoldat : Str -> N ; -- Soldat (, Soldaten) ; Kunde (, Kunden) (masc)
|
||||||
|
|
||||||
|
-- Neuter patterns.
|
||||||
|
|
||||||
|
nBuch : (_,_ : Str) -> N ; -- Buch, (Buches, Bücher) (neut)
|
||||||
|
nMesser : Str -> N ; -- Messer, (Messers, Messer) (neut)
|
||||||
|
nAuto : Str -> N ; -- Auto, (Autos, Autos) (neut)
|
||||||
|
|
||||||
|
-- Feminine patterns. Duplicated "e" is avoided in $nFrau$.
|
||||||
|
|
||||||
|
nHand : (_,_ : Str) -> N ; -- Hand, Hände; Mutter, Mütter (fem)
|
||||||
|
nFrau : Str -> N ; -- Frau (, Frauen) ; Wiese (, Wiesen) (fem)
|
||||||
|
|
||||||
|
|
||||||
|
-- Nouns used as functions need a preposition. The most common is "von".
|
||||||
|
|
||||||
|
mkFun : N -> Preposition -> Case -> Fun ;
|
||||||
|
funVon : N -> Fun ;
|
||||||
|
|
||||||
|
-- Proper names, with their possibly
|
||||||
|
-- irregular genitive. The regular genitive is "s", omitted after "s".
|
||||||
|
|
||||||
|
mkPN : (karolus, karoli : Str) -> PN ; -- karolus, karoli
|
||||||
|
pnReg : (Johann : Str) -> PN ; -- Johann, Johanns ; Johannes, Johannes
|
||||||
|
|
||||||
|
-- On the top level, it is maybe $CN$ that is used rather than $N$, and
|
||||||
|
-- $NP$ rather than $PN$.
|
||||||
|
|
||||||
|
mkCN : N -> CN ;
|
||||||
|
mkNP : (karolus,karoli : Str) -> NP ;
|
||||||
|
|
||||||
|
npReg : Str -> NP ; -- Johann, Johanns
|
||||||
|
|
||||||
|
-- In some cases, you may want to make a complex $CN$ into a function.
|
||||||
|
|
||||||
|
mkFunCN : CN -> Preposition -> Case -> Fun ;
|
||||||
|
funVonCN : CN -> Fun ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Adjectives
|
||||||
|
|
||||||
|
-- Non-comparison one-place adjectives need two forms in the worst case:
|
||||||
|
-- the one in predication and the one before the ending "e".
|
||||||
|
|
||||||
|
mkAdj1 : (teuer,teur : Str) -> Adj1 ;
|
||||||
|
|
||||||
|
-- Invariable adjective are a special case.
|
||||||
|
|
||||||
|
adjInvar : Str -> Adj1 ; -- prima
|
||||||
|
|
||||||
|
-- The following heuristic recognizes the the end of the word, and builds
|
||||||
|
-- the second form depending on if it is "e", "er", or something else.
|
||||||
|
-- N.B. a contraction is made with "er", which works for "teuer" but not
|
||||||
|
-- for "bitter".
|
||||||
|
|
||||||
|
adjGen : Str -> Adj1 ; -- gut; teuer; böse
|
||||||
|
|
||||||
|
-- Two-place adjectives need a preposition and a case as extra arguments.
|
||||||
|
|
||||||
|
mkAdj2 : Adj1 -> Str -> Case -> Adj2 ; -- teilbar, durch, acc
|
||||||
|
|
||||||
|
-- Comparison adjectives may need three adjective, corresponding to the
|
||||||
|
-- three comparison forms.
|
||||||
|
|
||||||
|
mkAdjDeg : (gut,besser,best : Adj1) -> AdjDeg ;
|
||||||
|
|
||||||
|
-- In many cases, each of these adjectives is itself regular. Then we only
|
||||||
|
-- need three strings. Notice that contraction with "er" is not performed
|
||||||
|
-- ("bessere", not "bessre").
|
||||||
|
|
||||||
|
aDeg3 : (gut,besser,best : Str) -> AdjDeg ;
|
||||||
|
|
||||||
|
-- In the completely regular case, the comparison forms are constructed by
|
||||||
|
-- the endings "er" and "st".
|
||||||
|
|
||||||
|
aReg : Str -> AdjDeg ; -- billig, billiger, billigst
|
||||||
|
|
||||||
|
-- The past participle of a verb can be used as an adjective.
|
||||||
|
|
||||||
|
aPastPart : V -> Adj1 ; -- gefangen
|
||||||
|
|
||||||
|
-- On top level, there are adjectival phrases. The most common case is
|
||||||
|
-- just to use a one-place adjective. The variation in $adjGen$ is taken
|
||||||
|
-- into account.
|
||||||
|
|
||||||
|
apReg : Str -> AP ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Verbs
|
||||||
|
--
|
||||||
|
-- The fragment only has present tense so far, but in all persons.
|
||||||
|
-- It also has the infinitive and the past participles.
|
||||||
|
-- The worst case macro needs four forms: : the infinitive and
|
||||||
|
-- the third person singular (where Umlaut may occur), the singular imperative,
|
||||||
|
-- and the past participle.
|
||||||
|
--
|
||||||
|
-- The function recognizes if the stem ends with "s" or "t" and performs the
|
||||||
|
-- appropriate contractions.
|
||||||
|
|
||||||
|
mkV : (_,_,_,_ : Str) -> V ; -- geben, gibt, gib, gegeben
|
||||||
|
|
||||||
|
-- Regular verbs are those where no Umlaut occurs.
|
||||||
|
|
||||||
|
vReg : Str -> V ; -- kommen
|
||||||
|
|
||||||
|
-- The verbs 'be' and 'have' are special.
|
||||||
|
|
||||||
|
vSein : V ;
|
||||||
|
vHaben : V ;
|
||||||
|
|
||||||
|
-- Verbs with a detachable particle, with regular ones as a special case.
|
||||||
|
|
||||||
|
vPart : (_,_,_,_,_ : Str) -> V ; -- sehen, sieht, sieh, gesehen, aus
|
||||||
|
vPartReg : (_,_ : Str) -> V ; -- bringen, um
|
||||||
|
|
||||||
|
-- Two-place verbs, and the special case with direct object. Notice that
|
||||||
|
-- a particle can be included in a $V$.
|
||||||
|
|
||||||
|
mkTV : V -> Str -> Case -> TV ; -- hören, zu, dative
|
||||||
|
|
||||||
|
tvReg : Str -> Str -> Case -> TV ; -- hören, zu, dative
|
||||||
|
tvDir : V -> TV ; -- umbringen
|
||||||
|
tvDirReg : Str -> TV ; -- lieben
|
||||||
|
|
||||||
|
--2 Adverbials
|
||||||
|
--
|
||||||
|
-- Adverbials for modifying verbs, adjectives, and sentences can be formed
|
||||||
|
-- from strings.
|
||||||
|
|
||||||
|
mkAdV : Str -> AdV ;
|
||||||
|
mkAdA : Str -> AdA ;
|
||||||
|
mkAdS : Str -> AdS ;
|
||||||
|
|
||||||
|
-- Prepositional phrases are another productive form of adverbials.
|
||||||
|
|
||||||
|
mkPP : Case -> Str -> NP -> AdV ;
|
||||||
|
|
||||||
|
-- The definitions should not bother the user of the API. So they are
|
||||||
|
-- hidden from the document.
|
||||||
|
--.
|
||||||
|
|
||||||
|
|
||||||
|
masculine = Masc ;
|
||||||
|
feminine = Fem ;
|
||||||
|
neuter = Neut ;
|
||||||
|
nominative = Nom ;
|
||||||
|
accusative = Acc ;
|
||||||
|
dative = Dat ;
|
||||||
|
genitive = Gen ;
|
||||||
|
-- singular defined in Types
|
||||||
|
-- plural defined in Types
|
||||||
|
|
||||||
|
mkN = mkNoun ;
|
||||||
|
|
||||||
|
nGen = \punkt, punktes, punkte, g -> let {
|
||||||
|
e = Predef.dp 1 punkte ;
|
||||||
|
eqy = ifTok (Gender -> N) e ;
|
||||||
|
noN = mkNoun4 punkt punktes punkte punkte
|
||||||
|
} in
|
||||||
|
eqy "n" noN (
|
||||||
|
eqy "s" noN (
|
||||||
|
mkNoun4 punkt punktes punkte (punkte+"n"))) g ;
|
||||||
|
|
||||||
|
nRaum = \raum, räume -> nGen raum (raum + "es") räume masculine ;
|
||||||
|
nTisch = \tisch ->
|
||||||
|
mkNoun4 tisch (tisch + "es") (tisch + "e") (tisch +"en") masculine ;
|
||||||
|
nVater = \vater, väter -> nGen vater (vater + "s") väter masculine ;
|
||||||
|
nFehler = \fehler -> nVater fehler fehler ;
|
||||||
|
|
||||||
|
nSoldat = \soldat -> let {
|
||||||
|
e = Predef.dp 1 soldat ;
|
||||||
|
soldaten = ifTok Tok e "e" (soldat + "n") (soldat + "en")
|
||||||
|
} in
|
||||||
|
mkN soldat soldaten soldaten soldaten soldaten soldaten masculine ;
|
||||||
|
|
||||||
|
nBuch = \buch, bücher -> nGen buch (buch + "es") bücher neuter ;
|
||||||
|
nMesser = \messer -> nGen messer (messer + "s") messer neuter ;
|
||||||
|
nAuto = \auto -> let {autos = auto + "s"} in
|
||||||
|
mkNoun4 auto autos autos autos neuter ;
|
||||||
|
|
||||||
|
nHand = \hand, hände -> nGen hand hand hände feminine ;
|
||||||
|
|
||||||
|
nFrau = \frau -> let {
|
||||||
|
e = Predef.dp 1 frau ;
|
||||||
|
frauen = ifTok Tok e "e" (frau + "n") (frau + "en")
|
||||||
|
} in
|
||||||
|
mkN frau frau frau frau frauen frauen feminine ;
|
||||||
|
|
||||||
|
mkFun = \n -> mkFunCN (n2n n) ;
|
||||||
|
funVon = \n -> funVonCN (n2n n) ;
|
||||||
|
|
||||||
|
mkPN = \karolus, karoli -> {s = table {Gen => karoli ; _ => karolus}} ;
|
||||||
|
pnReg = \horst ->
|
||||||
|
mkPN horst (ifTok Tok (Predef.dp 1 horst) "s" horst (horst + "s")) ;
|
||||||
|
|
||||||
|
mkCN = UseN ;
|
||||||
|
mkNP = \x,y -> UsePN (mkPN x y) ;
|
||||||
|
npReg = \s -> UsePN (pnReg s) ;
|
||||||
|
|
||||||
|
mkFunCN = mkFunC ;
|
||||||
|
funVonCN = funVonC ;
|
||||||
|
|
||||||
|
mkAdj1 = mkAdjective ;
|
||||||
|
adjInvar = Morpho.adjInvar ;
|
||||||
|
adjGen = Morpho.adjGen ;
|
||||||
|
mkAdj2 = \a,p,c -> a ** {s2 = p ; c = c} ;
|
||||||
|
|
||||||
|
mkAdjDeg = mkAdjComp ;
|
||||||
|
aDeg3 = adjCompReg3 ;
|
||||||
|
aReg = adjCompReg ;
|
||||||
|
aPastPart = \v -> {s = table AForm {a => v.s ! VPart a}} ;
|
||||||
|
apReg = \s -> AdjP1 (adjGen s) ;
|
||||||
|
|
||||||
|
mkV = \sehen, sieht, sieh, gesehen ->
|
||||||
|
mkVerbSimple (mkVerbum sehen sieht sieh gesehen) ;
|
||||||
|
vReg = \s -> mkVerbSimple (regVerb s) ;
|
||||||
|
vSein = verbSein ;
|
||||||
|
vHaben = verbHaben ;
|
||||||
|
vPart = \sehen, sieht, sieh, gesehen, aus ->
|
||||||
|
mkVerb (mkVerbum sehen sieht sieh gesehen) aus ;
|
||||||
|
vPartReg = \sehen, aus -> mkVerb (regVerb sehen) aus ;
|
||||||
|
|
||||||
|
mkTV = mkTransVerb ;
|
||||||
|
tvReg = \hören, zu, dat -> mkTV (vReg hören) zu dat ;
|
||||||
|
tvDir = \v -> mkTV v [] accusative ;
|
||||||
|
tvDirReg = \v -> tvReg v [] accusative ;
|
||||||
|
|
||||||
|
mkAdV = ss ;
|
||||||
|
mkPP = prepPhrase ;
|
||||||
|
mkAdA = ss ;
|
||||||
|
mkAdS = ss ;
|
||||||
|
} ;
|
||||||
87
grammars/resource/german/Predication.gf
Normal file
87
grammars/resource/german/Predication.gf
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
--1 A Small Predication Library
|
||||||
|
--
|
||||||
|
-- (c) Aarne Ranta 2003 under Gnu GPL.
|
||||||
|
--
|
||||||
|
-- This library is built on a language-independent API of
|
||||||
|
-- resource grammars. It has a common part, the type signatures
|
||||||
|
-- (defined here), and language-dependent parts. The user of
|
||||||
|
-- the library should only have to look at the type signatures.
|
||||||
|
|
||||||
|
resource Predication = open Deutsch in {
|
||||||
|
|
||||||
|
-- We first define a set of predication patterns.
|
||||||
|
|
||||||
|
oper
|
||||||
|
predV1 : V -> NP -> S ; -- one-place verb: "John walks"
|
||||||
|
predV2 : TV -> NP -> NP -> S ; -- two-place verb: "John loves Mary"
|
||||||
|
predVColl : V -> NP -> NP -> S ; -- collective verb: "John and Mary fight"
|
||||||
|
predA1 : Adj1 -> NP -> S ; -- one-place adjective: "John is old"
|
||||||
|
predA2 : Adj2 -> NP -> NP -> S ; -- two-place adj: "John is married to Mary"
|
||||||
|
predAComp : AdjDeg -> NP -> NP -> S ; -- compar adj: "John is older than Mary"
|
||||||
|
predAColl : Adj1 -> NP -> NP -> S ; -- collective adj: "John and Mary are married"
|
||||||
|
predN1 : N -> NP -> S ; -- one-place noun: "John is a man"
|
||||||
|
predN2 : Fun -> NP -> NP -> S ; -- two-place noun: "John is a lover of Mary"
|
||||||
|
predNColl : N -> NP -> NP -> S ; -- collective noun: "John and Mary are lovers"
|
||||||
|
|
||||||
|
-- Individual-valued function applications.
|
||||||
|
|
||||||
|
appFun1 : Fun -> NP -> NP ; -- one-place function: "the successor of x"
|
||||||
|
appFun2 : Fun -> NP -> NP -> NP ; -- two-place function: "the line from x to y"
|
||||||
|
appFunColl : Fun -> NP -> NP -> NP ; -- collective function: "the sum of x and y"
|
||||||
|
|
||||||
|
-- Families of types, expressed by common nouns depending on arguments.
|
||||||
|
|
||||||
|
appFam1 : Fun -> NP -> CN ; -- one-place family: "divisor of x"
|
||||||
|
appFam2 : Fun -> NP -> NP -> CN ; -- two-place family: "line from x to y"
|
||||||
|
appFamColl : Fun -> NP -> NP -> CN ; -- collective family: "path between x and y"
|
||||||
|
|
||||||
|
-- Type constructor, similar to a family except that the argument is a type.
|
||||||
|
|
||||||
|
constrTyp1 : Fun -> CN -> CN ;
|
||||||
|
|
||||||
|
-- Logical connectives on two sentences.
|
||||||
|
|
||||||
|
conjS : S -> S -> S ;
|
||||||
|
disjS : S -> S -> S ;
|
||||||
|
implS : S -> S -> S ;
|
||||||
|
|
||||||
|
-- As an auxiliary, we need two-place conjunction of names ("John and Mary"),
|
||||||
|
-- used in collective predication.
|
||||||
|
|
||||||
|
conjNP : NP -> NP -> NP ;
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
---- what follows should be an implementation of the preceding
|
||||||
|
|
||||||
|
oper
|
||||||
|
predV1 = \F, x -> PredVP x (PosV F) ;
|
||||||
|
predV2 = \F, x, y -> PredVP x (PosTV F y) ;
|
||||||
|
predVColl = \F, x, y -> PredVP (conjNP x y) (PosV F) ;
|
||||||
|
predA1 = \F, x -> PredVP x (PosA F) ;
|
||||||
|
predA2 = \F, x, y -> PredVP x (PosA (ComplAdj F y)) ;
|
||||||
|
predAComp = \F, x, y -> PredVP x (PosA (ComparAdjP F y)) ;
|
||||||
|
predAColl = \F, x, y -> PredVP (conjNP x y) (PosA F) ;
|
||||||
|
predN1 = \F, x -> PredVP x (PosCN (UseN F)) ;
|
||||||
|
predN2 = \F, x, y -> PredVP x (PosCN (AppFun F y)) ;
|
||||||
|
predNColl = \F, x, y -> PredVP (conjNP x y) (PosCN (UseN F)) ;
|
||||||
|
|
||||||
|
appFun1 = \f, x -> DefOneNP (AppFun f x) ;
|
||||||
|
appFun2 = \f, x, y -> DefOneNP (AppFun (AppFun2 f x) y) ;
|
||||||
|
appFunColl = \f, x, y -> DefOneNP (AppFun f (conjNP x y)) ;
|
||||||
|
|
||||||
|
appFam1 = \F, x -> AppFun F x ;
|
||||||
|
appFam2 = \F, x, y -> AppFun (AppFun2 F x) y ;
|
||||||
|
appFamColl = \F, x, y -> AppFun F (conjNP x y) ;
|
||||||
|
|
||||||
|
conjS = \A, B -> ConjS AndConj (TwoS A B) ;
|
||||||
|
disjS = \A, B -> ConjS OrConj (TwoS A B) ;
|
||||||
|
implS = \A, B -> SubjS IfSubj A B ;
|
||||||
|
|
||||||
|
constrTyp1 = \F, A -> AppFun F (IndefManyNP A) ;
|
||||||
|
|
||||||
|
conjNP = \x, y -> ConjNP AndConj (TwoNP x y) ;
|
||||||
|
|
||||||
|
} ;
|
||||||
217
grammars/resource/german/ResDeu.gf
Normal file
217
grammars/resource/german/ResDeu.gf
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
--1 The Top-Level German Resource Grammar
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002 -- 2003
|
||||||
|
--
|
||||||
|
-- This is the German concrete syntax of the multilingual resource
|
||||||
|
-- grammar. Most of the work is done in the file $syntax.Deu.gf$.
|
||||||
|
-- However, for the purpose of documentation, we make here explicit the
|
||||||
|
-- linearization types of each category, so that their structures and
|
||||||
|
-- dependencies can be seen.
|
||||||
|
-- Another substantial part are the linearization rules of some
|
||||||
|
-- structural words.
|
||||||
|
--
|
||||||
|
-- The users of the resource grammar should not look at this file for the
|
||||||
|
-- linearization rules, which are in fact hidden in the document version.
|
||||||
|
-- They should use $resource.Abs.gf$ to access the syntactic rules.
|
||||||
|
-- This file can be consulted in those, hopefully rare, occasions in which
|
||||||
|
-- one has to know how the syntactic categories are
|
||||||
|
-- implemented. The parameter types are defined in $Types.gf$.
|
||||||
|
|
||||||
|
concrete ResDeu of ResAbs = open Prelude, Syntax in {
|
||||||
|
|
||||||
|
flags
|
||||||
|
startcat=Phr ;
|
||||||
|
parser=chart ;
|
||||||
|
|
||||||
|
lincat
|
||||||
|
CN = CommNounPhrase ;
|
||||||
|
-- = {s : Adjf => Number => Case => Str ; g : Gender} ;
|
||||||
|
N = CommNoun ;
|
||||||
|
-- = {s : Number => Case => Str ; g : Gender} ;
|
||||||
|
NP = NounPhrase ;
|
||||||
|
-- = {s : NPForm => Str ; n : Number ; p : Person ; pro : Bool} ;
|
||||||
|
PN = ProperName ;
|
||||||
|
-- = {s : Case => Str} ;
|
||||||
|
Det = {s : Gender => Case => Str ; n : Number ; a : Adjf} ;
|
||||||
|
Fun = Function ;
|
||||||
|
-- = CommNounPhrase ** {s2 : Preposition ; c : Case} ;
|
||||||
|
Fun2 = Function ** {s3 : Preposition ; c2 : Case} ;
|
||||||
|
|
||||||
|
Adj1 = Adjective ;
|
||||||
|
-- = {s : AForm => Str} ;
|
||||||
|
Adj2 = Adjective ** {s2 : Preposition ; c : Case} ;
|
||||||
|
AdjDeg = {s : Degree => AForm => Str} ;
|
||||||
|
AP = Adjective ** {p : Bool} ;
|
||||||
|
|
||||||
|
V = Verb ;
|
||||||
|
-- = {s : VForm => Str ; s2 : Particle} ;
|
||||||
|
VP = Verb ** {s3 : Number => Str} ;
|
||||||
|
TV = Verb ** {s3 : Preposition ; c : Case} ;
|
||||||
|
VS = Verb ;
|
||||||
|
AdV = {s : Str} ;
|
||||||
|
|
||||||
|
S = Sentence ;
|
||||||
|
-- = {s : Order => Str} ;
|
||||||
|
Slash = Sentence ** {s2 : Preposition ; c : Case} ;
|
||||||
|
|
||||||
|
RP = {s : GenNum => Case => Str} ;
|
||||||
|
RC = {s : GenNum => Str} ;
|
||||||
|
|
||||||
|
IP = ProperName ** {n : Number} ;
|
||||||
|
Qu = {s : QuestForm => Str} ;
|
||||||
|
Imp = {s : Number => Str} ;
|
||||||
|
Phr = {s : Str} ;
|
||||||
|
Text = {s : Str} ;
|
||||||
|
|
||||||
|
Conj = {s : Str ; n : Number} ;
|
||||||
|
ConjD = {s1,s2 : Str ; n : Number} ;
|
||||||
|
|
||||||
|
ListS = {s1,s2 : Order => Str} ;
|
||||||
|
ListAP = {s1,s2 : AForm => Str ; p : Bool} ;
|
||||||
|
ListNP = {s1,s2 : NPForm => Str ; n : Number ; p : Person ; pro : Bool} ;
|
||||||
|
|
||||||
|
--.
|
||||||
|
|
||||||
|
lin
|
||||||
|
UseN = noun2CommNounPhrase ;
|
||||||
|
ModAdj = modCommNounPhrase ;
|
||||||
|
ModGenOne = npGenDet singular ;
|
||||||
|
ModGenMany = npGenDet plural ;
|
||||||
|
UsePN = nameNounPhrase ;
|
||||||
|
UseFun = funAsCommNounPhrase ;
|
||||||
|
AppFun = appFunComm ;
|
||||||
|
AppFun2 = appFun2 ;
|
||||||
|
AdjP1 = adj2adjPhrase ;
|
||||||
|
ComplAdj = complAdj ;
|
||||||
|
PositAdjP = positAdjPhrase ;
|
||||||
|
ComparAdjP = comparAdjPhrase ;
|
||||||
|
SuperlNP = superlNounPhrase ;
|
||||||
|
|
||||||
|
DetNP = detNounPhrase ;
|
||||||
|
IndefOneNP = indefNounPhrase singular ;
|
||||||
|
IndefManyNP = indefNounPhrase plural ;
|
||||||
|
DefOneNP = defNounPhrase singular ;
|
||||||
|
DefManyNP = defNounPhrase plural ;
|
||||||
|
|
||||||
|
CNthatS = nounThatSentence ;
|
||||||
|
|
||||||
|
PredVP = predVerbPhrase ;
|
||||||
|
PosV = predVerb True ;
|
||||||
|
NegV = predVerb False ;
|
||||||
|
PosA = predAdjective True ;
|
||||||
|
NegA = predAdjective False ;
|
||||||
|
PosCN = predCommNoun True ;
|
||||||
|
NegCN = predCommNoun False ;
|
||||||
|
PosTV = complTransVerb True ;
|
||||||
|
NegTV = complTransVerb False ;
|
||||||
|
PosPassV = passVerb True ;
|
||||||
|
NegPassV = passVerb False ;
|
||||||
|
PosNP = predNounPhrase True ;
|
||||||
|
NegNP = predNounPhrase False ;
|
||||||
|
PosVS = complSentVerb True ;
|
||||||
|
NegVS = complSentVerb False ;
|
||||||
|
|
||||||
|
AdvVP = adVerbPhrase ;
|
||||||
|
LocNP = locativeNounPhrase ;
|
||||||
|
AdvCN = advCommNounPhrase ;
|
||||||
|
AdvAP = advAdjPhrase ;
|
||||||
|
|
||||||
|
PosSlashTV = slashTransVerb True ;
|
||||||
|
NegSlashTV = slashTransVerb False ;
|
||||||
|
OneVP = predVerbPhrase (nameNounPhrase {s = \\_ => "man"}) ;
|
||||||
|
|
||||||
|
IdRP = identRelPron ;
|
||||||
|
FunRP = funRelPron ;
|
||||||
|
RelVP = relVerbPhrase ;
|
||||||
|
RelSlash = relSlash ;
|
||||||
|
ModRC = modRelClause ;
|
||||||
|
RelSuch = relSuch ;
|
||||||
|
|
||||||
|
WhoOne = intPronWho singular ;
|
||||||
|
WhoMany = intPronWho plural ;
|
||||||
|
WhatOne = intPronWhat singular ;
|
||||||
|
WhatMany = intPronWhat plural ;
|
||||||
|
FunIP = funIntPron ;
|
||||||
|
NounIPOne = nounIntPron singular ;
|
||||||
|
NounIPMany = nounIntPron plural ;
|
||||||
|
|
||||||
|
QuestVP = questVerbPhrase ;
|
||||||
|
IntVP = intVerbPhrase ;
|
||||||
|
IntSlash = intSlash ;
|
||||||
|
QuestAdv = questAdverbial ;
|
||||||
|
|
||||||
|
ImperVP = imperVerbPhrase ;
|
||||||
|
|
||||||
|
IndicPhrase = indicUtt ;
|
||||||
|
QuestPhrase = interrogUtt ;
|
||||||
|
ImperOne = imperUtterance singular ;
|
||||||
|
ImperMany = imperUtterance plural ;
|
||||||
|
|
||||||
|
AdvS = advSentence ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
TwoS = twoSentence ;
|
||||||
|
ConsS = consSentence ;
|
||||||
|
ConjS = conjunctSentence ;
|
||||||
|
ConjDS = conjunctDistrSentence ;
|
||||||
|
|
||||||
|
TwoAP = twoAdjPhrase ;
|
||||||
|
ConsAP = consAdjPhrase ;
|
||||||
|
ConjAP = conjunctAdjPhrase ;
|
||||||
|
ConjDAP = conjunctDistrAdjPhrase ;
|
||||||
|
|
||||||
|
TwoNP = twoNounPhrase ;
|
||||||
|
ConsNP = consNounPhrase ;
|
||||||
|
ConjNP = conjunctNounPhrase ;
|
||||||
|
ConjDNP = conjunctDistrNounPhrase ;
|
||||||
|
|
||||||
|
SubjS = subjunctSentence ;
|
||||||
|
SubjImper = subjunctImperative ;
|
||||||
|
SubjQu = subjunctQuestion ;
|
||||||
|
|
||||||
|
PhrNP = useNounPhrase ;
|
||||||
|
PhrOneCN = useCommonNounPhrase singular ;
|
||||||
|
PhrManyCN = useCommonNounPhrase plural ;
|
||||||
|
PhrIP ip = ip ;
|
||||||
|
PhrIAdv ia = ia ;
|
||||||
|
|
||||||
|
OnePhr p = p ;
|
||||||
|
ConsPhr = cc2 ;
|
||||||
|
|
||||||
|
INP = pronNounPhrase pronIch ;
|
||||||
|
ThouNP = pronNounPhrase pronDu ;
|
||||||
|
HeNP = pronNounPhrase pronEr ;
|
||||||
|
SheNP = pronNounPhrase pronSie ;
|
||||||
|
ItNP = pronNounPhrase pronEs ;
|
||||||
|
WeNP = pronNounPhrase pronWir ;
|
||||||
|
YeNP = pronNounPhrase pronIhr ;
|
||||||
|
TheyNP = pronNounPhrase pronSiePl ;
|
||||||
|
|
||||||
|
YouNP = pronNounPhrase pronSSie ;
|
||||||
|
|
||||||
|
EveryDet = jederDet ;
|
||||||
|
AllDet = alleDet ;
|
||||||
|
WhichDet = welcherDet ;
|
||||||
|
MostDet = meistDet ;
|
||||||
|
|
||||||
|
HowIAdv = ss "wie" ;
|
||||||
|
WhenIAdv = ss "wann" ;
|
||||||
|
WhereIAdv = ss "war" ;
|
||||||
|
WhyIAdv = ss "warum" ;
|
||||||
|
|
||||||
|
AndConj = ss "und" ** {n = Pl} ;
|
||||||
|
OrConj = ss "oder" ** {n = Sg} ;
|
||||||
|
BothAnd = sd2 "sowohl" ["als auch"] ** {n = Pl} ;
|
||||||
|
EitherOr = sd2 "entweder" "oder" ** {n = Sg} ;
|
||||||
|
NeitherNor = sd2 "weder" "noch" ** {n = Sg} ;
|
||||||
|
IfSubj = ss "wenn" ;
|
||||||
|
WhenSubj = ss "wenn" ;
|
||||||
|
|
||||||
|
PhrYes = ss ["Ja ."] ;
|
||||||
|
PhrNo = ss ["Nein ."] ;
|
||||||
|
|
||||||
|
VeryAdv = ss "sehr" ;
|
||||||
|
TooAdv = ss "zu" ;
|
||||||
|
OtherwiseAdv = ss "sonst" ;
|
||||||
|
ThereforeAdv = ss "deshalb" ;
|
||||||
|
} ;
|
||||||
24
grammars/resource/german/RestaurantDeu.gf
Normal file
24
grammars/resource/german/RestaurantDeu.gf
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
concrete RestaurantDeu of Restaurant =
|
||||||
|
DatabaseDeu ** open Prelude,Paradigms,Deutsch,DatabaseRes in {
|
||||||
|
|
||||||
|
lin
|
||||||
|
Restaurant = UseN (nAuto "Restaurant") ;
|
||||||
|
Bar = UseN (nAuto "Bar") ; --- ??
|
||||||
|
French = apReg "Französisch" ;
|
||||||
|
Italian = apReg "Italienisch" ;
|
||||||
|
Indian = apReg "Indisch" ;
|
||||||
|
Japanese = apReg "Japanisch" ;
|
||||||
|
|
||||||
|
address = funVon (nFrau "Adresse") ;
|
||||||
|
phone = funVon (nFrau "Rufnummer") ; ----
|
||||||
|
priceLevel = funVon (nFrau "Preisstufe") ;
|
||||||
|
|
||||||
|
Cheap = aReg "billig" ;
|
||||||
|
Expensive = aDeg3 "teuer" "teurer" "teurest" ;
|
||||||
|
|
||||||
|
WhoRecommend rest = mkSentSame (ss2 ["wer empfiehlt"] (rest.s ! accusative)) ;
|
||||||
|
WhoHellRecommend rest =
|
||||||
|
mkSentSame (ss2 ["wer zum Teufel empfiehlt"] (rest.s ! accusative)) ;
|
||||||
|
|
||||||
|
LucasCarton = mkPN ["Lucas Carton"] ["Lucas Cartons"] ;
|
||||||
|
} ;
|
||||||
891
grammars/resource/german/Syntax.gf
Normal file
891
grammars/resource/german/Syntax.gf
Normal file
@@ -0,0 +1,891 @@
|
|||||||
|
--1 A Small German Resource Syntax
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002
|
||||||
|
--
|
||||||
|
-- This resource grammar contains definitions needed to construct
|
||||||
|
-- indicative, interrogative, and imperative sentences in German.
|
||||||
|
--
|
||||||
|
-- The following modules are presupposed:
|
||||||
|
|
||||||
|
resource Syntax = Morpho ** open Prelude, (CO = Coordination) in {
|
||||||
|
|
||||||
|
--2 Common Nouns
|
||||||
|
--
|
||||||
|
-- Simple common nouns are defined as the type $CommNoun$ in $morpho.Deu.gf$.
|
||||||
|
|
||||||
|
--3 Common noun phrases
|
||||||
|
|
||||||
|
-- The need for this more complex type comes from the variation in the way in
|
||||||
|
-- which a modifying adjective is inflected after different determiners.
|
||||||
|
-- We use the $Adjf$ parameter for this ($Strong$/$Weak$).
|
||||||
|
|
||||||
|
oper
|
||||||
|
|
||||||
|
CommNounPhrase : Type = {s : Adjf => Number => Case => Str ; g : Gender} ;
|
||||||
|
|
||||||
|
noun2CommNounPhrase : CommNoun -> CommNounPhrase = \haus ->
|
||||||
|
{s = \\_ => haus.s ; g = haus.g} ;
|
||||||
|
|
||||||
|
n2n = noun2CommNounPhrase ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--2 Noun phrases
|
||||||
|
--
|
||||||
|
-- The worst case is pronouns, which have inflection in the possessive
|
||||||
|
-- forms. Other noun phrases express all possessive forms with the genitive case.
|
||||||
|
-- The parameter $pro$ tells if the $NP$ is a pronoun, which is needed in e.g.
|
||||||
|
-- genitive constructions.
|
||||||
|
|
||||||
|
NounPhrase : Type = {
|
||||||
|
s : NPForm => Str ;
|
||||||
|
n : Number ;
|
||||||
|
p : Person ;
|
||||||
|
pro : Bool
|
||||||
|
} ;
|
||||||
|
|
||||||
|
pronNounPhrase : ProPN -> NounPhrase = \ich ->
|
||||||
|
ich ** {pro = True} ;
|
||||||
|
|
||||||
|
caseNP : NPForm -> Case = \np -> case np of {
|
||||||
|
NPCase c => c ;
|
||||||
|
NPPoss _ _ => Gen
|
||||||
|
} ;
|
||||||
|
|
||||||
|
normalNounPhrase : (Case => Str) -> Number -> NounPhrase = \cs,n ->
|
||||||
|
{s = \\c => cs ! caseNP c ;
|
||||||
|
n = n ;
|
||||||
|
p = P3 ; -- third person
|
||||||
|
pro = False -- not a pronoun
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Proper names are a simple kind of noun phrases. They can usually
|
||||||
|
-- be constructed from strings in a regular way.
|
||||||
|
|
||||||
|
ProperName : Type = {s : Case => Str} ;
|
||||||
|
|
||||||
|
nameNounPhrase : ProperName -> NounPhrase = \john ->
|
||||||
|
{s = \\np => john.s ! caseNP np ; n = Sg ; p = P3 ; pro = False} ;
|
||||||
|
|
||||||
|
mkProperName : Str -> ProperName = \horst ->
|
||||||
|
{s = table {Gen => horst + "s" ; _ => horst}} ;
|
||||||
|
|
||||||
|
--2 Determiners
|
||||||
|
--
|
||||||
|
-- Determiners are inflected according to the nouns they determine.
|
||||||
|
-- The determiner determines the number and adjectival form from the determiner.
|
||||||
|
|
||||||
|
Determiner : Type = {s : Gender => Case => Str ; n : Number ; a : Adjf} ;
|
||||||
|
|
||||||
|
detNounPhrase : Determiner -> CommNounPhrase -> NounPhrase = \ein, mann ->
|
||||||
|
{s = \\c => let {nc = caseNP c} in
|
||||||
|
ein.s ! mann.g ! nc ++ mann.s ! adjfCas ein.a nc ! ein.n ! nc ;
|
||||||
|
p = P3 ;
|
||||||
|
n = ein.n ;
|
||||||
|
pro = False
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- The adjectival form after a determiner depends both on the inferent form
|
||||||
|
-- and on the case ("ein alter Mann" but "einem alten Mann").
|
||||||
|
|
||||||
|
adjfCas : Adjf -> Case -> Adjf = \a,c -> case <a,c> of {
|
||||||
|
<Strong,Nom> => Strong ;
|
||||||
|
<Strong,Acc> => Strong ;
|
||||||
|
_ => Weak
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- The following macros are sufficient to define most determiners,
|
||||||
|
-- as shown by the examples that follow.
|
||||||
|
|
||||||
|
DetSg = Gender => Case => Str ;
|
||||||
|
DetPl = Case => Str ;
|
||||||
|
|
||||||
|
mkDeterminerSg : DetSg -> Adjf -> Determiner = \ein, a ->
|
||||||
|
{s = ein ; n = Sg ; a = a} ;
|
||||||
|
|
||||||
|
mkDeterminerPl : DetPl -> Adjf -> Determiner = \alle, a ->
|
||||||
|
{s = \\_ => alle ; n = Pl ; a = a} ;
|
||||||
|
|
||||||
|
detLikeAdj : Str -> Determiner = \jed -> mkDeterminerSg
|
||||||
|
(\\g,c => (adjReg jed).s ! AMod Strong (GSg g) c) Weak ;
|
||||||
|
|
||||||
|
jederDet = detLikeAdj "jed" ;
|
||||||
|
alleDet = mkDeterminerPl (caselist "alle" "alle" "allen" "aller") Weak ;
|
||||||
|
einDet = mkDeterminerSg artIndef Strong ;
|
||||||
|
derDet = mkDeterminerSg (table {g => artDef ! GSg g}) Weak ;
|
||||||
|
dieDet = mkDeterminerPl (artDef ! GPl) Weak ;
|
||||||
|
|
||||||
|
meistDet = mkDeterminerPl (table {c => artDef ! GPl ! c ++ "meisten"}) Weak ;
|
||||||
|
welcherDet = detLikeAdj "welch" ;
|
||||||
|
welcheDet = mkDeterminerPl (caselist "welche" "welche" "welchen" "welcher") Weak ;
|
||||||
|
|
||||||
|
-- Choose "welcher"/"welche"
|
||||||
|
|
||||||
|
welchDet : Number -> Determiner = \n ->
|
||||||
|
case n of {Sg => welcherDet ; Pl => welcheDet} ;
|
||||||
|
|
||||||
|
-- Genitives of noun phrases can be used like determiners, to build noun phrases.
|
||||||
|
-- The number argument makes the difference between "mein Haus" - "meine Häuser".
|
||||||
|
--
|
||||||
|
-- If the 'owner' is a pronoun, only one form is available "mein Haus".
|
||||||
|
-- In other cases, two variants are available: "Johanns Haus" / "das Haus Johanns".
|
||||||
|
|
||||||
|
npGenDet : Number -> NounPhrase -> CommNounPhrase -> NounPhrase = \n,haus,Wein ->
|
||||||
|
let {
|
||||||
|
hauses : Case => Str = \\c => haus.s ! NPPoss (gNumber Wein.g n) c ;
|
||||||
|
wein : NPForm => Str = \\c => Wein.s ! Strong ! n ! caseNP c ;
|
||||||
|
derwein : NPForm => Str = (defNounPhrase n Wein).s
|
||||||
|
}
|
||||||
|
in
|
||||||
|
{s = \\c => variants {
|
||||||
|
hauses ! caseNP c ++ wein ! c ;
|
||||||
|
if_then_else Str haus.pro
|
||||||
|
nonExist
|
||||||
|
(derwein ! c ++ hauses ! Nom) -- the case does not matter
|
||||||
|
} ;
|
||||||
|
p = P3 ;
|
||||||
|
n = n ;
|
||||||
|
pro = False
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- *Bare plural noun phrases* like "Männer", "gute Häuser", are built without a
|
||||||
|
-- determiner word.
|
||||||
|
|
||||||
|
plurDet : CommNounPhrase -> NounPhrase = \cn ->
|
||||||
|
normalNounPhrase (cn.s ! Strong ! Pl) Pl ;
|
||||||
|
|
||||||
|
-- Macros for indef/def Sg/Pl noun phrases are needed in many places even
|
||||||
|
-- if they might not be constituents.
|
||||||
|
|
||||||
|
indefNounPhrase : Number -> CommNounPhrase -> NounPhrase = \n,haus -> case n of {
|
||||||
|
Sg => detNounPhrase einDet haus ;
|
||||||
|
Pl => plurDet haus
|
||||||
|
} ;
|
||||||
|
|
||||||
|
defNounPhrase : Number -> CommNounPhrase -> NounPhrase = \n,haus -> case n of {
|
||||||
|
Sg => detNounPhrase derDet haus ;
|
||||||
|
Pl => detNounPhrase dieDet haus
|
||||||
|
} ;
|
||||||
|
|
||||||
|
indefNoun : Number -> CommNounPhrase -> Str = \n, mann -> case n of {
|
||||||
|
Sg => (detNounPhrase einDet mann).s ! NPCase Nom ;
|
||||||
|
Pl => (plurDet mann).s ! NPCase Nom
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Constructions like "die Idee, dass zwei gerade ist" are formed at the
|
||||||
|
-- first place as common nouns, so that one can also have "ein Vorschlag, dass...".
|
||||||
|
|
||||||
|
nounThatSentence : CommNounPhrase -> Sentence -> CommNounPhrase = \idee,x ->
|
||||||
|
{s = \\a,n,c => idee.s ! a! n ! c ++ [", dass"] ++ x.s ! Sub ;
|
||||||
|
g = idee.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--2 Adjectives
|
||||||
|
--
|
||||||
|
-- Adjectival phrases have a parameter $p$ telling if postposition is
|
||||||
|
-- allowed (complex APs).
|
||||||
|
|
||||||
|
AdjPhrase : Type = Adjective ** {p : Bool} ;
|
||||||
|
|
||||||
|
adj2adjPhrase : Adjective -> AdjPhrase = \ny -> ny ** {p = False} ;
|
||||||
|
|
||||||
|
--3 Comparison adjectives
|
||||||
|
--
|
||||||
|
-- The type is defined in $types.Deu.gf$.
|
||||||
|
|
||||||
|
AdjDegr : Type = AdjComp ;
|
||||||
|
|
||||||
|
-- Each of the comparison forms has a characteristic use:
|
||||||
|
--
|
||||||
|
-- Positive forms are used alone, as adjectival phrases ("jung").
|
||||||
|
|
||||||
|
positAdjPhrase : AdjDegr -> AdjPhrase = \jung ->
|
||||||
|
{s = jung.s ! Pos ; p = False} ;
|
||||||
|
|
||||||
|
-- Comparative forms are used with an object of comparison, as
|
||||||
|
-- adjectival phrases ("besser als Rolf").
|
||||||
|
|
||||||
|
comparAdjPhrase : AdjDegr -> NounPhrase -> AdjPhrase = \besser,rolf ->
|
||||||
|
{s = \\a => besser.s ! Comp ! a ++ "als" ++ rolf.s ! NPCase Nom ;
|
||||||
|
p = True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Superlative forms are used with a common noun, picking out the
|
||||||
|
-- maximal representative of a domain ("der Jüngste Mann").
|
||||||
|
|
||||||
|
superlNounPhrase : AdjDegr -> CommNounPhrase -> NounPhrase = \best,mann ->
|
||||||
|
let {gen = mann.g} in
|
||||||
|
{s = \\c => let {nc = caseNP c} in
|
||||||
|
artDef ! gNumber gen Sg ! nc ++
|
||||||
|
best.s ! Sup ! aMod Weak gen Sg nc ++
|
||||||
|
mann.s ! Weak ! Sg ! nc ;
|
||||||
|
p = P3 ;
|
||||||
|
n = Sg ;
|
||||||
|
pro = False
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--3 Two-place adjectives
|
||||||
|
--
|
||||||
|
-- A two-place adjective is an adjective with a preposition used before
|
||||||
|
-- the complement, and the complement case.
|
||||||
|
|
||||||
|
AdjCompl = Adjective ** {s2 : Preposition ; c : Case} ;
|
||||||
|
|
||||||
|
complAdj : AdjCompl -> NounPhrase -> AdjPhrase = \verwandt,dich ->
|
||||||
|
{s = \\a =>
|
||||||
|
bothWays (verwandt.s ! a) (verwandt.s2 ++ dich.s ! NPCase verwandt.c) ;
|
||||||
|
p = True
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--3 Modification of common nouns
|
||||||
|
--
|
||||||
|
-- The two main functions of adjective are in predication ("Johann ist jung")
|
||||||
|
-- and in modification ("ein junger Mann"). Predication will be defined
|
||||||
|
-- later, in the chapter on verbs.
|
||||||
|
--
|
||||||
|
-- Modification must pay attention to pre- and post-noun
|
||||||
|
-- adjectives: "gutes Haus"; "besseres als X haus" / "haus besseres als X"
|
||||||
|
|
||||||
|
modCommNounPhrase : AdjPhrase -> CommNounPhrase -> CommNounPhrase = \gut,haus ->
|
||||||
|
{s = \\a,n,c => let {
|
||||||
|
gutes = gut.s ! aMod a haus.g n c ;
|
||||||
|
Haus = haus.s ! a ! n ! c
|
||||||
|
} in
|
||||||
|
if_then_else Str gut.p (bothWays gutes Haus) (gutes ++ Haus) ;
|
||||||
|
g = haus.g} ;
|
||||||
|
|
||||||
|
--2 Function expressions
|
||||||
|
|
||||||
|
-- A function expression is a common noun together with the
|
||||||
|
-- preposition prefixed to its argument ("Mutter von x").
|
||||||
|
-- The type is analogous to two-place adjectives and transitive verbs.
|
||||||
|
|
||||||
|
Function = CommNounPhrase ** {s2 : Preposition ; c : Case} ;
|
||||||
|
|
||||||
|
-- The application of a function gives, in the first place, a common noun:
|
||||||
|
-- "Mutter/Mütter von Johann". From this, other rules of the resource grammar
|
||||||
|
-- give noun phrases, such as "die Mutter von Johann", "die Mütter von Johann",
|
||||||
|
-- "die Mütter von Johann und Maria", and "die Mutter von Johann und Maria" (the
|
||||||
|
-- latter two corresponding to distributive and collective functions,
|
||||||
|
-- respectively). Semantics will eventually tell when each
|
||||||
|
-- of the readings is meaningful.
|
||||||
|
|
||||||
|
appFunComm : Function -> NounPhrase -> CommNounPhrase = \mutter,uwe ->
|
||||||
|
{s = \\a,n,c => mutter.s ! a ! n ! c ++ mutter.s2 ++ uwe.s ! NPCase mutter.c ;
|
||||||
|
g = mutter.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- It is possible to use a function word as a common noun; the semantics is
|
||||||
|
-- often existential or indexical.
|
||||||
|
|
||||||
|
funAsCommNounPhrase : Function -> CommNounPhrase = \x -> x ;
|
||||||
|
|
||||||
|
-- The following is an aggregate corresponding to the original function application
|
||||||
|
-- producing "Johanns Mutter" and "die Mutter von Johann". It does not appear in the
|
||||||
|
-- resource grammar API any longer.
|
||||||
|
|
||||||
|
appFun : Bool -> Function -> NounPhrase -> NounPhrase = \coll, mutter, uwe ->
|
||||||
|
let {n = uwe.n ; g = mutter.g ; nf = if_then_else Number coll Sg n} in
|
||||||
|
variants {
|
||||||
|
defNounPhrase nf (appFunComm mutter uwe) ;
|
||||||
|
npGenDet nf uwe mutter
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- The commonest cases are functions with "von" and functions with Genitive.
|
||||||
|
|
||||||
|
mkFunC : CommNounPhrase -> Preposition -> Case -> Function = \f,p,c ->
|
||||||
|
f ** {s2 = p ; c = c} ;
|
||||||
|
|
||||||
|
funVonC : CommNounPhrase -> Function = \wert ->
|
||||||
|
mkFunC wert "von" Dat ;
|
||||||
|
|
||||||
|
funGenC : CommNounPhrase -> Function = \wert ->
|
||||||
|
mkFunC wert [] Gen ;
|
||||||
|
|
||||||
|
-- Two-place functions add one argument place.
|
||||||
|
|
||||||
|
Function2 = Function ** {s3 : Preposition ; c2 : Case} ;
|
||||||
|
|
||||||
|
-- There application starts by filling the first place.
|
||||||
|
|
||||||
|
appFun2 : Function2 -> NounPhrase -> Function = \flug, paris ->
|
||||||
|
{s = \\a,n,c => flug.s ! a ! n ! c ++ flug.s2 ++ paris.s ! NPCase flug.c ;
|
||||||
|
g = flug.g ;
|
||||||
|
s2 = flug.s3 ;
|
||||||
|
c = flug.c2
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Verbs
|
||||||
|
--
|
||||||
|
--3 Verb phrases
|
||||||
|
--
|
||||||
|
-- Verb phrases are discontinuous: the parts of a verb phrase are
|
||||||
|
-- (s) an inflected verb, (s2) particle, and
|
||||||
|
-- (s3) negation and complement. This discontinuity is needed in sentence formation
|
||||||
|
-- to account for word order variations.
|
||||||
|
|
||||||
|
VerbPhrase = Verb ** {s3 : Number => Str} ;
|
||||||
|
|
||||||
|
-- A simple verb can be made into a verb phrase with an empty complement.
|
||||||
|
-- There are two versions, depending on if we want to negate the verb.
|
||||||
|
-- N.B. negation is *not* a function applicable to a verb phrase, since
|
||||||
|
-- double negations with "nicht" are not grammatical.
|
||||||
|
|
||||||
|
predVerb : Bool -> Verb -> VerbPhrase = \b,aussehen ->
|
||||||
|
aussehen ** {
|
||||||
|
s3 = \\_ => negation b
|
||||||
|
} ;
|
||||||
|
|
||||||
|
negation : Bool -> Str = \b -> if_then_else Str b [] "nicht" ;
|
||||||
|
|
||||||
|
-- Sometimes we want to extract the verb part of a verb phrase.
|
||||||
|
|
||||||
|
verbOfPhrase : VerbPhrase -> Verb = \v -> {s = v.s ; s2 = v.s2} ;
|
||||||
|
|
||||||
|
-- Verb phrases can also be formed from adjectives ("ist gut"),
|
||||||
|
-- common nouns ("ist ein Mann"), and noun phrases ("ist der jüngste Mann").
|
||||||
|
-- The third rule is overgenerating: "ist jeder Mann" has to be ruled out
|
||||||
|
-- on semantic grounds.
|
||||||
|
|
||||||
|
predAdjective : Bool -> Adjective -> VerbPhrase = \b,gut ->
|
||||||
|
verbSein ** {
|
||||||
|
s3 = \\_ => negation b ++ gut.s ! APred
|
||||||
|
} ;
|
||||||
|
|
||||||
|
predCommNoun : Bool -> CommNounPhrase -> VerbPhrase = \b,man ->
|
||||||
|
verbSein ** {
|
||||||
|
s3 = \\n => negation b ++ indefNoun n man
|
||||||
|
} ;
|
||||||
|
|
||||||
|
predNounPhrase : Bool -> NounPhrase -> VerbPhrase = \b,dermann ->
|
||||||
|
verbSein ** {
|
||||||
|
s3 = \\n => negation b ++ dermann.s ! NPCase Nom
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--3 Transitive verbs
|
||||||
|
--
|
||||||
|
-- Transitive verbs are verbs with a preposition for the complement,
|
||||||
|
-- in analogy with two-place adjectives and functions.
|
||||||
|
-- One might prefer to use the term "2-place verb", since
|
||||||
|
-- "transitive" traditionally means that the inherent preposition is empty.
|
||||||
|
-- Such a verb is one with a *direct object* - which may still be accusative,
|
||||||
|
-- dative, or genitive.
|
||||||
|
|
||||||
|
TransVerb = Verb ** {s3 : Preposition ; c : Case} ;
|
||||||
|
|
||||||
|
mkTransVerb : Verb -> Preposition -> Case -> TransVerb =
|
||||||
|
\v,p,c -> v ** {s3 = p ; c = c} ;
|
||||||
|
|
||||||
|
-- The rule for using transitive verbs is the complementization rule:
|
||||||
|
|
||||||
|
complTransVerb : Bool -> TransVerb -> NounPhrase -> VerbPhrase =
|
||||||
|
\b,warten,dich ->
|
||||||
|
let {
|
||||||
|
aufdich = warten.s3 ++ dich.s ! NPCase warten.c ;
|
||||||
|
nicht = negation b
|
||||||
|
} in
|
||||||
|
{s = warten.s ;
|
||||||
|
s2 = warten.s2 ;
|
||||||
|
s3 = \\_ => bothWays aufdich nicht
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Transitive verbs with accusative objects can be used passively.
|
||||||
|
-- The function does not check that the verb is transitive.
|
||||||
|
-- Therefore, the function can also be used for "es wird gelaufen", etc.
|
||||||
|
|
||||||
|
passVerb : Bool -> Verb -> VerbPhrase = \b,lieben ->
|
||||||
|
{s = verbumWerden ;
|
||||||
|
s2 = [] ;
|
||||||
|
s3 = \\_ => negation b ++ lieben.s ! VPart APred
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Adverbials
|
||||||
|
--
|
||||||
|
-- Adverbials are not inflected (we ignore comparison, and treat
|
||||||
|
-- compared adverbials as separate expressions; this could be done another way).
|
||||||
|
|
||||||
|
Adverb : Type = SS ;
|
||||||
|
|
||||||
|
mkAdverb : Str -> Adverb = ss ;
|
||||||
|
|
||||||
|
adVerbPhrase : VerbPhrase -> Adverb -> VerbPhrase = \spielt, gut ->
|
||||||
|
{s = spielt.s ;
|
||||||
|
s2 = spielt.s2 ;
|
||||||
|
s3 = \\n => spielt.s3 ! n ++ gut.s
|
||||||
|
} ;
|
||||||
|
|
||||||
|
advAdjPhrase : Adverb -> AdjPhrase -> AdjPhrase = \sehr, gut ->
|
||||||
|
{s = \\a => sehr.s ++ gut.s ! a ;
|
||||||
|
p = gut.p
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Adverbials are typically generated by prefixing prepositions.
|
||||||
|
-- The rule for creating locative noun phrases by the preposition "in"
|
||||||
|
-- is a little shaky, since other prepositions may be preferred ("an", "auf").
|
||||||
|
|
||||||
|
prepPhrase : Case -> Preposition -> NounPhrase -> Adverb = \c,auf,ihm ->
|
||||||
|
ss (auf ++ ihm.s ! NPCase c) ;
|
||||||
|
|
||||||
|
locativeNounPhrase : NounPhrase -> Adverb =
|
||||||
|
prepPhrase Dat "in" ;
|
||||||
|
|
||||||
|
-- This is a source of the "Mann mit einem Teleskop" ambiguity, and may produce
|
||||||
|
-- strange things, like "Autos immer" (while "Autos heute" is OK).
|
||||||
|
-- Semantics will have to make finer distinctions among adverbials.
|
||||||
|
|
||||||
|
advCommNounPhrase : CommNounPhrase -> Adverb -> CommNounPhrase = \haus,heute ->
|
||||||
|
{s = \\a, n, c => haus.s ! a ! n ! c ++ heute.s ;
|
||||||
|
g = haus.g} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--2 Sentences
|
||||||
|
--
|
||||||
|
-- Sentences depend on a *word order parameter* selecting between main clause,
|
||||||
|
-- inverted, and subordinate clause.
|
||||||
|
|
||||||
|
Sentence : Type = SS1 Order ;
|
||||||
|
|
||||||
|
-- This is the traditional $S -> NP VP$ rule. It takes care of both
|
||||||
|
-- word order and agreement.
|
||||||
|
|
||||||
|
predVerbPhrase : NounPhrase -> VerbPhrase -> Sentence =
|
||||||
|
\Ich,LiebeDichNichtAus ->
|
||||||
|
let {
|
||||||
|
ich = Ich.s ! NPCase Nom ;
|
||||||
|
liebe = LiebeDichNichtAus.s ! VInd Ich.n Ich.p ;
|
||||||
|
aus = LiebeDichNichtAus.s2 ;
|
||||||
|
dichnichtgut = LiebeDichNichtAus.s3 ! Ich.n
|
||||||
|
} in
|
||||||
|
{s = table {
|
||||||
|
Main => ich ++ liebe ++ dichnichtgut ++ aus ;
|
||||||
|
Inv => liebe ++ ich ++ dichnichtgut ++ aus ;
|
||||||
|
Sub => ich ++ dichnichtgut ++ aus ++ liebe
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--3 Sentence-complement verbs
|
||||||
|
--
|
||||||
|
-- Sentence-complement verbs take sentences as complements.
|
||||||
|
|
||||||
|
SentenceVerb : Type = Verb ;
|
||||||
|
|
||||||
|
complSentVerb : Bool -> SentenceVerb -> Sentence -> VerbPhrase = \b,sage,duisst ->
|
||||||
|
sage **
|
||||||
|
{s3 = \\_ => negation b ++ "," ++ "dass" ++ duisst.s ! Sub} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Sentences missing noun phrases
|
||||||
|
--
|
||||||
|
-- This is one instance of Gazdar's *slash categories*, corresponding to his
|
||||||
|
-- $S/NP$.
|
||||||
|
-- We cannot have - nor would we want to have - a productive slash-category former.
|
||||||
|
-- Perhaps a handful more will be needed.
|
||||||
|
--
|
||||||
|
-- Notice that the slash category has the same relation to sentences as
|
||||||
|
-- transitive verbs have to verbs: it's like a *sentence taking a complement*.
|
||||||
|
|
||||||
|
SentenceSlashNounPhrase : Type = Sentence ** {s2 : Preposition ; c : Case} ;
|
||||||
|
|
||||||
|
slashTransVerb : Bool -> NounPhrase -> TransVerb -> SentenceSlashNounPhrase =
|
||||||
|
\b, Ich, sehen ->
|
||||||
|
let {
|
||||||
|
ich = Ich.s ! NPCase Nom ;
|
||||||
|
sehe = sehen.s ! VInd Ich.n P3 ;
|
||||||
|
aus = sehen.s2 ;
|
||||||
|
nicht = negation b
|
||||||
|
} in
|
||||||
|
{s = table {
|
||||||
|
Main => ich ++ sehe ++ nicht ++ aus ;
|
||||||
|
Inv => sehe ++ ich ++ nicht ++ aus ;
|
||||||
|
Sub => ich ++ nicht ++ aus ++ sehe
|
||||||
|
} ;
|
||||||
|
s2 = sehen.s3 ;
|
||||||
|
c = sehen.c
|
||||||
|
} ;
|
||||||
|
|
||||||
|
--2 Relative pronouns and relative clauses
|
||||||
|
--
|
||||||
|
-- Relative pronouns are inflected in
|
||||||
|
-- gender, number, and case just like adjectives.
|
||||||
|
|
||||||
|
oper
|
||||||
|
identRelPron : RelPron = relPron ;
|
||||||
|
|
||||||
|
funRelPron : Function -> RelPron -> RelPron = \wert, der ->
|
||||||
|
{s = \\gn,c => let {nu = numGenNum gn} in
|
||||||
|
artDef ! gNumber wert.g nu ! c ++ wert.s ! Weak ! nu ! c ++
|
||||||
|
wert.s2 ++ der.s ! gn ! wert.c
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- Relative clauses can be formed from both verb phrases ("der schläft") and
|
||||||
|
-- slash expressions ("den ich sehe", "auf dem ich sitze").
|
||||||
|
|
||||||
|
RelClause : Type = {s : GenNum => Str} ;
|
||||||
|
|
||||||
|
relVerbPhrase : RelPron -> VerbPhrase -> RelClause = \der, geht ->
|
||||||
|
{s = \\gn => (predVerbPhrase (normalNounPhrase (der.s ! gn) (numGenNum gn))
|
||||||
|
geht
|
||||||
|
).s ! Sub
|
||||||
|
} ;
|
||||||
|
|
||||||
|
relSlash : RelPron -> SentenceSlashNounPhrase -> RelClause = \den, ichSehe ->
|
||||||
|
{s = \\gn => ichSehe.s2 ++ den.s ! gn ! ichSehe.c ++ ichSehe.s ! Sub
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- A 'degenerate' relative clause is the one often used in mathematics, e.g.
|
||||||
|
-- "Zahl x derart, dass x gerade ist".
|
||||||
|
|
||||||
|
relSuch : Sentence -> RelClause = \A ->
|
||||||
|
{s = \\_ => "derart" ++ "dass" ++ A.s ! Sub} ;
|
||||||
|
|
||||||
|
-- The main use of relative clauses is to modify common nouns.
|
||||||
|
-- The result is a common noun, out of which noun phrases can be formed
|
||||||
|
-- by determiners. A comma is used before the relative clause.
|
||||||
|
|
||||||
|
modRelClause : CommNounPhrase -> RelClause -> CommNounPhrase = \mann,dergeht ->
|
||||||
|
{s = \\a,n,c => mann.s ! a ! n ! c ++ "," ++ dergeht.s ! gNumber mann.g n ;
|
||||||
|
g = mann.g
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Interrogative pronouns
|
||||||
|
--
|
||||||
|
-- If relative pronouns are adjective-like, interrogative pronouns are
|
||||||
|
-- noun-phrase-like. We use a simplified type, since we don't need the possessive
|
||||||
|
-- forms.
|
||||||
|
|
||||||
|
IntPron : Type = ProperName ** {n : Number} ;
|
||||||
|
|
||||||
|
-- In analogy with relative pronouns, we have a rule for applying a function
|
||||||
|
-- to a relative pronoun to create a new one.
|
||||||
|
|
||||||
|
funIntPron : Function -> IntPron -> IntPron = \wert, wer ->
|
||||||
|
let {n = wer.n} in
|
||||||
|
{s = \\c =>
|
||||||
|
artDef ! gNumber wert.g n ! c ++ wert.s ! Weak ! n ! c ++
|
||||||
|
wert.s2 ++ wer.s ! wert.c ;
|
||||||
|
n = n
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- There is a variety of simple interrogative pronouns:
|
||||||
|
-- "welches Haus", "wer", "was".
|
||||||
|
|
||||||
|
nounIntPron : Number -> CommNounPhrase -> IntPron = \n,cn ->
|
||||||
|
let {np = detNounPhrase (welchDet n) cn} in
|
||||||
|
{s = \\c => np.s ! NPCase c ;
|
||||||
|
n = np.n} ;
|
||||||
|
|
||||||
|
intPronWho : Number -> IntPron = \num -> {
|
||||||
|
s = caselist "wer" "wen" "wem" "weren" ;
|
||||||
|
n = num
|
||||||
|
} ;
|
||||||
|
|
||||||
|
intPronWhat : Number -> IntPron = \num -> {
|
||||||
|
s = caselist "was" "was" nonExist nonExist ; ---
|
||||||
|
n = num
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--2 Utterances
|
||||||
|
|
||||||
|
-- By utterances we mean whole phrases, such as
|
||||||
|
-- 'can be used as moves in a language game': indicatives, questions, imperative,
|
||||||
|
-- and one-word utterances. The rules are far from complete.
|
||||||
|
--
|
||||||
|
-- N.B. we have not included rules for texts, which we find we cannot say much
|
||||||
|
-- about on this level. In semantically rich GF grammars, texts, dialogues, etc,
|
||||||
|
-- will of course play an important role as categories not reducible to utterances.
|
||||||
|
-- An example is proof texts, whose semantics show a dependence between premises
|
||||||
|
-- and conclusions. Another example is intersentential anaphora.
|
||||||
|
|
||||||
|
Utterance = SS ;
|
||||||
|
|
||||||
|
indicUtt : Sentence -> Utterance = \x -> ss (x.s ! Main ++ ".") ;
|
||||||
|
interrogUtt : Question -> Utterance = \x -> ss (x.s ! DirQ ++ "?") ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Questions
|
||||||
|
--
|
||||||
|
-- Questions are either direct ("bist du müde") or indirect
|
||||||
|
-- ("ob du müde bist").
|
||||||
|
|
||||||
|
param
|
||||||
|
QuestForm = DirQ | IndirQ ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
Question = SS1 QuestForm ;
|
||||||
|
|
||||||
|
--3 Yes-no questions
|
||||||
|
--
|
||||||
|
-- Yes-no questions are used both independently ("bist du müde")
|
||||||
|
-- and after interrogative adverbials ("warum bist du müde").
|
||||||
|
-- It is economical to handle with these two cases by the one
|
||||||
|
-- rule, $questVerbPhrase'$. The only difference is if "ob" appears
|
||||||
|
-- in the indirect form.
|
||||||
|
|
||||||
|
questVerbPhrase : NounPhrase -> VerbPhrase -> Question =
|
||||||
|
questVerbPhrase' False ;
|
||||||
|
|
||||||
|
questVerbPhrase' : Bool -> NounPhrase -> VerbPhrase -> Question =
|
||||||
|
\adv, du,gehst ->
|
||||||
|
let {dugehst = (predVerbPhrase du gehst).s} in
|
||||||
|
{s = table {
|
||||||
|
DirQ => dugehst ! Inv ;
|
||||||
|
IndirQ => (if_then_else Str adv [] "ob") ++ dugehst ! Sub
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Wh-questions
|
||||||
|
--
|
||||||
|
-- Wh-questions are of two kinds: ones that are like $NP - VP$ sentences,
|
||||||
|
-- others that are line $S/NP - NP$ sentences.
|
||||||
|
|
||||||
|
intVerbPhrase : IntPron -> VerbPhrase -> Question = \Wer,geht ->
|
||||||
|
let {wer : NounPhrase = normalNounPhrase Wer.s Wer.n ;
|
||||||
|
wergeht : Sentence = predVerbPhrase wer geht
|
||||||
|
} in
|
||||||
|
{s = table {
|
||||||
|
DirQ => wergeht.s ! Main ;
|
||||||
|
IndirQ => wergeht.s ! Sub
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
intSlash : IntPron -> SentenceSlashNounPhrase -> Question = \wer, ichSehe ->
|
||||||
|
let {zuwen = ichSehe.s2 ++ wer.s ! ichSehe.c} in
|
||||||
|
{s = table {
|
||||||
|
DirQ => zuwen ++ ichSehe.s ! Inv ;
|
||||||
|
IndirQ => zuwen ++ ichSehe.s ! Sub
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Interrogative adverbials
|
||||||
|
--
|
||||||
|
-- These adverbials will be defined in the lexicon: they include
|
||||||
|
-- "wann", "war", "wie", "warum", etc, which are all invariant one-word
|
||||||
|
-- expressions. In addition, they can be formed by adding prepositions
|
||||||
|
-- to interrogative pronouns, in the same way as adverbials are formed
|
||||||
|
-- from noun phrases.
|
||||||
|
|
||||||
|
IntAdverb = SS ;
|
||||||
|
|
||||||
|
prepIntAdverb : Case -> Preposition -> IntPron -> IntAdverb =\ c,auf,wem ->
|
||||||
|
ss (auf ++ wem.s ! c) ;
|
||||||
|
|
||||||
|
-- A question adverbial can be applied to anything, and whether this makes
|
||||||
|
-- sense is a semantic question.
|
||||||
|
|
||||||
|
questAdverbial : IntAdverb -> NounPhrase -> VerbPhrase -> Question =
|
||||||
|
\wie, du, tust ->
|
||||||
|
{s = \\q => wie.s ++ (questVerbPhrase du tust).s ! q} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Imperatives
|
||||||
|
--
|
||||||
|
-- We only consider second-person imperatives. No polite "Sie" form so far.
|
||||||
|
|
||||||
|
Imperative = SS1 Number ;
|
||||||
|
|
||||||
|
imperVerbPhrase : VerbPhrase -> Imperative = \komm ->
|
||||||
|
{s = \\n => komm.s ! VImp n ++ komm.s3 ! n ++ komm.s2} ;
|
||||||
|
|
||||||
|
imperUtterance : Number -> Imperative -> Utterance = \n,I ->
|
||||||
|
ss (I.s ! n ++ "!") ;
|
||||||
|
|
||||||
|
--2 Sentence adverbials
|
||||||
|
--
|
||||||
|
-- This class covers adverbials such as "sonst", "folgelich", which are prefixed
|
||||||
|
-- to a sentence to form a phrase; the sentence gets inverted word order.
|
||||||
|
|
||||||
|
advSentence : Adverb -> Sentence -> Utterance = \sonst,ist1gerade ->
|
||||||
|
ss (sonst.s ++ ist1gerade.s ! Inv ++ ".") ;
|
||||||
|
|
||||||
|
--2 Coordination
|
||||||
|
--
|
||||||
|
-- Coordination is to some extent orthogonal to the rest of syntax, and
|
||||||
|
-- has been treated in a generic way in the module $CO$ in the file
|
||||||
|
-- $coordination.gf$. The overall structure is independent of category,
|
||||||
|
-- but there can be differences in parameter dependencies.
|
||||||
|
--
|
||||||
|
--3 Conjunctions
|
||||||
|
--
|
||||||
|
-- Coordinated phrases are built by using conjunctions, which are either
|
||||||
|
-- simple ("und", "oder") or distributed ("sowohl - als auch", "entweder - oder").
|
||||||
|
--
|
||||||
|
-- The conjunction has an inherent number, which is used when conjoining
|
||||||
|
-- noun phrases: "John und Mary sind..." vs. "John oder Mary ist..."; in the
|
||||||
|
-- case of "oder", the result is however plural if any of the disjuncts is.
|
||||||
|
|
||||||
|
Conjunction = CO.Conjunction ** {n : Number} ;
|
||||||
|
ConjunctionDistr = CO.ConjunctionDistr ** {n : Number} ;
|
||||||
|
|
||||||
|
|
||||||
|
--3 Coordinating sentences
|
||||||
|
--
|
||||||
|
-- We need a category of lists of sentences. It is a discontinuous
|
||||||
|
-- category, the parts corresponding to 'init' and 'last' segments
|
||||||
|
-- (rather than 'head' and 'tail', because we have to keep track of the slot between
|
||||||
|
-- the last two elements of the list). A list has at least two elements.
|
||||||
|
|
||||||
|
ListSentence : Type = {s1,s2 : Order => Str} ;
|
||||||
|
|
||||||
|
twoSentence : (_,_ : Sentence) -> ListSentence =
|
||||||
|
CO.twoTable Order ;
|
||||||
|
|
||||||
|
consSentence : ListSentence -> Sentence -> ListSentence =
|
||||||
|
CO.consTable Order CO.comma ;
|
||||||
|
|
||||||
|
-- To coordinate a list of sentences by a simple conjunction, we place
|
||||||
|
-- it between the last two elements; commas are put in the other slots,
|
||||||
|
-- e.g. "du rauchst, er trinkt und ich esse".
|
||||||
|
|
||||||
|
conjunctSentence : Conjunction -> ListSentence -> Sentence =
|
||||||
|
CO.conjunctTable Order ;
|
||||||
|
|
||||||
|
-- To coordinate a list of sentences by a distributed conjunction, we place
|
||||||
|
-- the first part (e.g. "entweder") in front of the first element, the second
|
||||||
|
-- part ("oder") between the last two elements, and commas in the other slots.
|
||||||
|
-- For sentences this is really not used.
|
||||||
|
|
||||||
|
conjunctDistrSentence : ConjunctionDistr -> ListSentence -> Sentence =
|
||||||
|
CO.conjunctDistrTable Order ;
|
||||||
|
|
||||||
|
--3 Coordinating adjective phrases
|
||||||
|
--
|
||||||
|
-- The structure is the same as for sentences. The result is a prefix adjective
|
||||||
|
-- if and only if all elements are prefix.
|
||||||
|
|
||||||
|
ListAdjPhrase : Type =
|
||||||
|
{s1,s2 : AForm => Str ; p : Bool} ;
|
||||||
|
|
||||||
|
twoAdjPhrase : (_,_ : AdjPhrase) -> ListAdjPhrase = \x,y ->
|
||||||
|
CO.twoTable AForm x y ** {p = andB x.p y.p} ;
|
||||||
|
consAdjPhrase : ListAdjPhrase -> AdjPhrase -> ListAdjPhrase = \xs,x ->
|
||||||
|
CO.consTable AForm CO.comma xs x ** {p = andB xs.p x.p} ;
|
||||||
|
|
||||||
|
conjunctAdjPhrase : Conjunction -> ListAdjPhrase -> AdjPhrase = \c,xs ->
|
||||||
|
CO.conjunctTable AForm c xs ** {p = xs.p} ;
|
||||||
|
|
||||||
|
conjunctDistrAdjPhrase : ConjunctionDistr -> ListAdjPhrase -> AdjPhrase = \c,xs ->
|
||||||
|
CO.conjunctDistrTable AForm c xs ** {p = xs.p} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--3 Coordinating noun phrases
|
||||||
|
--
|
||||||
|
-- The structure is the same as for sentences. The result is either always plural
|
||||||
|
-- or plural if any of the components is, depending on the conjunction.
|
||||||
|
-- The result is a pronoun if all components are.
|
||||||
|
|
||||||
|
ListNounPhrase : Type =
|
||||||
|
{s1,s2 : NPForm => Str ; n : Number ; p : Person ; pro : Bool} ;
|
||||||
|
|
||||||
|
twoNounPhrase : (_,_ : NounPhrase) -> ListNounPhrase = \x,y ->
|
||||||
|
CO.twoTable NPForm x y **
|
||||||
|
{n = conjNumber x.n y.n ; p = conjPerson x.p y.p ; pro = andB x.pro y.pro} ;
|
||||||
|
|
||||||
|
consNounPhrase : ListNounPhrase -> NounPhrase -> ListNounPhrase = \xs,x ->
|
||||||
|
CO.consTable NPForm CO.comma xs x **
|
||||||
|
{n = conjNumber xs.n x.n ; p = conjPerson xs.p x.p ; pro = andB xs.pro x.pro} ;
|
||||||
|
|
||||||
|
conjunctNounPhrase : Conjunction -> ListNounPhrase -> NounPhrase = \c,xs ->
|
||||||
|
CO.conjunctTable NPForm c xs **
|
||||||
|
{n = conjNumber c.n xs.n ; p = xs.p ; pro = xs.pro} ;
|
||||||
|
|
||||||
|
conjunctDistrNounPhrase : ConjunctionDistr -> ListNounPhrase -> NounPhrase =
|
||||||
|
\c,xs ->
|
||||||
|
CO.conjunctDistrTable NPForm c xs **
|
||||||
|
{n = conjNumber c.n xs.n ; p = xs.p ; pro = xs.pro} ;
|
||||||
|
|
||||||
|
-- We have to define a calculus of numbers of persons. For numbers,
|
||||||
|
-- it is like the conjunction with $Pl$ corresponding to $False$.
|
||||||
|
|
||||||
|
conjNumber : Number -> Number -> Number = \m,n -> case <m,n> of {
|
||||||
|
<Sg,Sg> => Sg ;
|
||||||
|
_ => Pl
|
||||||
|
} ;
|
||||||
|
|
||||||
|
-- For persons, we go in the descending order:
|
||||||
|
-- "ich und dich sind stark", "er oder du bist stark".
|
||||||
|
-- This is not always quite clear.
|
||||||
|
|
||||||
|
conjPerson : Person -> Person -> Person = \p,q -> case <p,q> of {
|
||||||
|
<P3,P3> => P3 ;
|
||||||
|
<P1,_> => P1 ;
|
||||||
|
<_,P1> => P1 ;
|
||||||
|
_ => P2
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Subjunction
|
||||||
|
--
|
||||||
|
-- Subjunctions ("wenn", "falls", etc)
|
||||||
|
-- are a different way to combine sentences than conjunctions.
|
||||||
|
-- The main clause can be a sentences, an imperatives, or a question,
|
||||||
|
-- but the subjoined clause must be a sentence.
|
||||||
|
|
||||||
|
Subjunction = SS ;
|
||||||
|
|
||||||
|
subjunctSentence : Subjunction -> Sentence -> Sentence -> Sentence = \if, A, B ->
|
||||||
|
let {As = A.s ! Sub} in
|
||||||
|
{s = table {
|
||||||
|
Main => variants {if.s ++ As ++ "," ++ B.s ! Inv ;
|
||||||
|
B.s ! Main ++ "," ++ if.s ++ As} ;
|
||||||
|
o => B.s ! o ++ "," ++ if.s ++ As
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
subjunctImperative : Subjunction -> Sentence -> Imperative -> Imperative =
|
||||||
|
\if, A, B ->
|
||||||
|
{s = \\n => subjunctVariants if A (B.s ! n)} ;
|
||||||
|
|
||||||
|
subjunctQuestion : Subjunction -> Sentence -> Question -> Question = \if, A, B ->
|
||||||
|
{s = \\q => subjunctVariants if A (B.s ! q)} ;
|
||||||
|
|
||||||
|
-- There are uniformly two variant word orders, e.g.
|
||||||
|
-- "wenn du rauchst, werde ish böse"
|
||||||
|
-- and "ich werde böse, wenn du rauchst".
|
||||||
|
|
||||||
|
subjunctVariants : Subjunction -> Sentence -> Str -> Str = \if,A,B ->
|
||||||
|
let {As = A.s ! Sub} in
|
||||||
|
variants {if.s ++ As ++ "," ++ B ; B ++ "," ++ if.s ++ As} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 One-word utterances
|
||||||
|
--
|
||||||
|
-- An utterance can consist of one phrase of almost any category,
|
||||||
|
-- the limiting case being one-word utterances. These
|
||||||
|
-- utterances are often (but not always) in what can be called the
|
||||||
|
-- default form of a category, e.g. the nominative.
|
||||||
|
-- This list is far from exhaustive.
|
||||||
|
|
||||||
|
useNounPhrase : NounPhrase -> Utterance = \john ->
|
||||||
|
postfixSS "." (defaultNounPhrase john) ;
|
||||||
|
useCommonNounPhrase : Number -> CommNounPhrase -> Utterance = \n,car ->
|
||||||
|
useNounPhrase (indefNounPhrase n car) ;
|
||||||
|
|
||||||
|
-- Here are some default forms.
|
||||||
|
|
||||||
|
defaultNounPhrase : NounPhrase -> SS = \john ->
|
||||||
|
ss (john.s ! NPCase Nom) ;
|
||||||
|
|
||||||
|
defaultQuestion : Question -> SS = \whoareyou ->
|
||||||
|
ss (whoareyou.s ! DirQ) ;
|
||||||
|
|
||||||
|
defaultSentence : Sentence -> Utterance = \x -> ss (x.s ! Main) ;
|
||||||
|
|
||||||
|
--3 Puzzle
|
||||||
|
--
|
||||||
|
-- Adding some lexicon, we can generate the sentence
|
||||||
|
--
|
||||||
|
-- "der grösste alte Mann ist nicht ein Auto auf die Mutter von dem Männer warten"
|
||||||
|
--
|
||||||
|
-- which looks completely ungrammatical! What you should do to decipher it is
|
||||||
|
-- put parentheses around "auf die Mutter von dem".
|
||||||
|
|
||||||
|
} ;
|
||||||
39
grammars/resource/german/TestDeu.gf
Normal file
39
grammars/resource/german/TestDeu.gf
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
concrete TestDeu of TestAbs = ResDeu ** open Syntax in {
|
||||||
|
|
||||||
|
flags startcat=Phr ; lexer=text ; parser=chart ; unlexer=text ;
|
||||||
|
|
||||||
|
-- a random sample from the lexicon
|
||||||
|
|
||||||
|
lin
|
||||||
|
Big = adjCompReg3 "gross" "grösser" "grösst";
|
||||||
|
Small = adjCompReg "klein" ;
|
||||||
|
Old = adjCompReg3 "alt" "älter" "ältest";
|
||||||
|
Young = adjCompReg3 "jung" "jünger" "jüngst";
|
||||||
|
Man = declN2u "Mann" "Männer" ;
|
||||||
|
Woman = declN1 "Frau" ;
|
||||||
|
Car = declNs "Auto" ;
|
||||||
|
House = declN3uS "Haus" "Häuser" ;
|
||||||
|
Light = declN3 "Licht" ;
|
||||||
|
Walk = mkVerbSimple (verbLaufen "gehen" "geht" "gegangen") ;
|
||||||
|
Run = mkVerbSimple (verbLaufen "laufen" "läuft" "gelaufen") ;
|
||||||
|
Say = mkVerbSimple (regVerb "sagen") ;
|
||||||
|
Prove = mkVerbSimple (regVerb "beweisen") ;
|
||||||
|
Send = mkTransVerb (mkVerbSimple (verbLaufen "senden" "sendet" "gesandt")) [] Acc;
|
||||||
|
Love = mkTransVerb (mkVerbSimple (regVerb "lieben")) [] Acc ;
|
||||||
|
Wait = mkTransVerb (mkVerbSimple (verbWarten "warten")) "auf" Acc ;
|
||||||
|
Mother = mkFunC (n2n (declN2uF "Mutter" "Mütter")) "von" Dat ;
|
||||||
|
Uncle = mkFunC (n2n (declN2i "Onkel")) "von" Dat ;
|
||||||
|
Connection = mkFunC (n2n (declN1 "Verbindung")) "von" Dat **
|
||||||
|
{s3 = "nach" ; c2 = Dat} ;
|
||||||
|
|
||||||
|
Always = mkAdverb "immer" ;
|
||||||
|
Well = mkAdverb "gut" ;
|
||||||
|
|
||||||
|
SwitchOn = mkTransVerb (mkVerb (verbWarten "schalten") "auf") [] Acc ;
|
||||||
|
SwitchOff = mkTransVerb (mkVerb (verbWarten "schalten") "aus") [] Acc ;
|
||||||
|
|
||||||
|
John = mkProperName "Johann" ;
|
||||||
|
Mary = mkProperName "Maria" ;
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
98
grammars/resource/german/Types.gf
Normal file
98
grammars/resource/german/Types.gf
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
--1 German Word Classes and Morphological Parameters
|
||||||
|
--
|
||||||
|
-- This is a resource module for German morphology, defining the
|
||||||
|
-- morphological parameters and word classes of German. It is so far only
|
||||||
|
-- complete w.r.t. the syntax part of the resource grammar.
|
||||||
|
-- It does not include those parameters that are not needed for
|
||||||
|
-- analysing individual words: such parameters are defined in syntax modules.
|
||||||
|
--
|
||||||
|
|
||||||
|
resource Types = open Prelude in {
|
||||||
|
|
||||||
|
--2 Enumerated parameter types
|
||||||
|
--
|
||||||
|
-- These types are the ones found in school grammars.
|
||||||
|
-- Their parameter values are atomic.
|
||||||
|
|
||||||
|
param
|
||||||
|
Number = Sg | Pl ;
|
||||||
|
Gender = Masc | Fem | Neut ;
|
||||||
|
Person = P1 | P2 | P3 ;
|
||||||
|
Case = Nom | Acc | Dat | Gen ;
|
||||||
|
Adjf = Strong | Weak ; -- the main division in adjective declension
|
||||||
|
Order = Main | Inv | Sub ; -- word order: direct, indirect, subordinate
|
||||||
|
|
||||||
|
-- For abstraction and API compatibility, we define two synonyms:
|
||||||
|
|
||||||
|
oper
|
||||||
|
singular = Sg ;
|
||||||
|
plural = Pl ;
|
||||||
|
|
||||||
|
--2 Word classes and hierarchical parameter types
|
||||||
|
--
|
||||||
|
-- Real parameter types (i.e. ones on which words and phrases depend)
|
||||||
|
-- are mostly hierarchical. The alternative is cross-products of
|
||||||
|
-- simple parameters, but this cannot be always used since it overgenerates.
|
||||||
|
--
|
||||||
|
|
||||||
|
--3 Common nouns
|
||||||
|
--
|
||||||
|
-- Common nouns are inflected in number and case and they have an inherent gender.
|
||||||
|
|
||||||
|
CommNoun : Type = {s : Number => Case => Str ; g : Gender} ;
|
||||||
|
|
||||||
|
--3 Pronouns
|
||||||
|
--
|
||||||
|
-- Pronouns are an example - the worst-case one of noun phrases,
|
||||||
|
-- which are properly defined in $syntax.Deu.gf$.
|
||||||
|
-- Their inflection tables has, in addition to the normal genitive,
|
||||||
|
-- the possessive forms, which are inflected like determiners.
|
||||||
|
|
||||||
|
param
|
||||||
|
NPForm = NPCase Case | NPPoss GenNum Case ;
|
||||||
|
|
||||||
|
--3 Adjectives
|
||||||
|
--
|
||||||
|
-- Adjectives are a very complex class, and the full table has as many as
|
||||||
|
-- 99 different forms. The major division is between the comparison degrees.
|
||||||
|
-- There is no gender distinction in the plural,
|
||||||
|
-- and the predicative forms ("X ist Adj") are not inflected.
|
||||||
|
|
||||||
|
param
|
||||||
|
GenNum = GSg Gender | GPl ;
|
||||||
|
AForm = APred | AMod Adjf GenNum Case ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
Adjective : Type = {s : AForm => Str} ;
|
||||||
|
AdjComp : Type = {s : Degree => AForm => Str} ;
|
||||||
|
|
||||||
|
-- Comparison of adjectives:
|
||||||
|
|
||||||
|
param Degree = Pos | Comp | Sup ;
|
||||||
|
|
||||||
|
--3 Verbs
|
||||||
|
--
|
||||||
|
-- We have a reduced conjugation with only the present tense infinitive,
|
||||||
|
-- indicative, and imperative forms, and past participles.
|
||||||
|
|
||||||
|
param VForm = VInf | VInd Number Person | VImp Number | VPart AForm ;
|
||||||
|
|
||||||
|
oper Verbum : Type = VForm => Str ;
|
||||||
|
|
||||||
|
-- On the general level, we have to account for composite verbs as well,
|
||||||
|
-- such as "aus" + "sehen" etc.
|
||||||
|
|
||||||
|
Particle = Str ;
|
||||||
|
|
||||||
|
Verb = {s : Verbum ; s2 : Particle} ;
|
||||||
|
|
||||||
|
|
||||||
|
--2 Prepositions
|
||||||
|
--
|
||||||
|
-- We define prepositions simply as strings. Thus we do not capture the
|
||||||
|
-- contractions "vom", "ins", etc. To define them in GF grammar we would need
|
||||||
|
-- to introduce a parameter system, which we postpone.
|
||||||
|
|
||||||
|
Preposition = Str ;
|
||||||
|
|
||||||
|
} ;
|
||||||
1039
grammars/resource/swedish/Morpho.gf
Normal file
1039
grammars/resource/swedish/Morpho.gf
Normal file
File diff suppressed because it is too large
Load Diff
196
grammars/resource/swedish/ResSwe.gf
Normal file
196
grammars/resource/swedish/ResSwe.gf
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
--1 The Top-Level Swedish Resource Grammar
|
||||||
|
--
|
||||||
|
-- Aarne Ranta 2002 -- 2003
|
||||||
|
--
|
||||||
|
-- This is the Swedish concrete syntax of the multilingual resource
|
||||||
|
-- grammar. Most of the work is done in the file $syntax.Swe.gf$.
|
||||||
|
-- However, for the purpose of documentation, we make here explicit the
|
||||||
|
-- linearization types of each category, so that their structures and
|
||||||
|
-- dependencies can be seen.
|
||||||
|
-- Another substantial part are the linearization rules of some
|
||||||
|
-- structural words.
|
||||||
|
--
|
||||||
|
-- The users of the resource grammar should not look at this file for the
|
||||||
|
-- linearization rules, which are in fact hidden in the document version.
|
||||||
|
-- They should use $resource.Abs.gf$ to access the syntactic rules.
|
||||||
|
-- This file can be consulted in those, hopefully rare, occasions in which
|
||||||
|
-- one has to know how the syntactic categories are
|
||||||
|
-- implemented. The parameter types are defined in $Types.gf$.
|
||||||
|
|
||||||
|
concrete ResSwe of ResAbs = open Prelude, Syntax in {
|
||||||
|
|
||||||
|
flags
|
||||||
|
startcat=Phr ;
|
||||||
|
parser=chart ;
|
||||||
|
|
||||||
|
lincat
|
||||||
|
CN = {s : Number => SpeciesP => Case => Str ; g : Gender ; x : Sex ;
|
||||||
|
p : IsComplexCN} ;
|
||||||
|
N = CommNoun ;
|
||||||
|
-- = {s : Number => Species => Case => Str ; g : Gender ; x : Sex} ;
|
||||||
|
NP = NounPhrase ;
|
||||||
|
-- = {s : NPForm => Str ; g : Gender ; n : Number} ;
|
||||||
|
PN = {s : Case => Str ; g : Gender ; x : Sex} ;
|
||||||
|
Det = {s : Gender => Sex => Str ; n : Number ; b : SpeciesP} ;
|
||||||
|
Fun = CommNoun ** {s2 : Preposition} ;
|
||||||
|
|
||||||
|
Adj1 = Adjective ;
|
||||||
|
-- = {s : AdjFormPos => Case => Str} ;
|
||||||
|
Adj2 = Adjective ** {s2 : Preposition} ;
|
||||||
|
AdjDeg = {s : AdjForm => Str} ;
|
||||||
|
AP = Adjective ** {p : IsPostfixAdj} ;
|
||||||
|
|
||||||
|
V = Verb ;
|
||||||
|
-- = {s : VForm => Str} ;
|
||||||
|
VP = Verb ** {s2 : Str ; s3 : Gender => Number => Str} ;
|
||||||
|
TV = Verb ** {s2 : Preposition} ;
|
||||||
|
VS = Verb ;
|
||||||
|
|
||||||
|
AdV = {s : Str ; isPost : Bool} ;
|
||||||
|
|
||||||
|
S = Sentence ;
|
||||||
|
-- = {s : Order => Str} ;
|
||||||
|
Slash = Sentence ** {s2 : Preposition} ;
|
||||||
|
RP = {s : RelCase => GenNum => Str ; g : RelGender} ;
|
||||||
|
RC = {s : GenNum => Str} ;
|
||||||
|
IP = NounPhrase ;
|
||||||
|
Qu = {s : QuestForm => Str} ;
|
||||||
|
Imp = {s : Number => Str} ;
|
||||||
|
|
||||||
|
Phr = {s : Str} ;
|
||||||
|
|
||||||
|
Conj = {s : Str ; n : Number} ;
|
||||||
|
ConjD = {s1 : Str ; s2 : Str ; n : Number} ;
|
||||||
|
|
||||||
|
ListS = {s1,s2 : Order => Str} ;
|
||||||
|
ListAP = {s1,s2 : AdjFormPos => Case => Str ; p : Bool} ;
|
||||||
|
ListNP = {s1,s2 : NPForm => Str ; g : Gender ; n : Number} ;
|
||||||
|
|
||||||
|
--.
|
||||||
|
|
||||||
|
lin
|
||||||
|
UseN = noun2CommNounPhrase ;
|
||||||
|
ModAdj = modCommNounPhrase ;
|
||||||
|
ModGenOne = npGenDet singular ;
|
||||||
|
ModGenMany = npGenDet plural ;
|
||||||
|
UsePN = nameNounPhrase ;
|
||||||
|
UseFun = funAsCommNounPhrase ;
|
||||||
|
AppFun = appFunComm ;
|
||||||
|
AdjP1 = adj2adjPhrase ;
|
||||||
|
ComplAdj = complAdj ;
|
||||||
|
PositAdjP = positAdjPhrase ;
|
||||||
|
ComparAdjP = comparAdjPhrase ;
|
||||||
|
SuperlNP = superlNounPhrase ;
|
||||||
|
|
||||||
|
DetNP = detNounPhrase ;
|
||||||
|
IndefOneNP = indefNounPhrase singular ;
|
||||||
|
IndefManyNP = indefNounPhrase plural ;
|
||||||
|
DefOneNP = defNounPhrase singular ;
|
||||||
|
DefManyNP = defNounPhrase plural ;
|
||||||
|
|
||||||
|
PredVP = predVerbPhrase ;
|
||||||
|
PosV = predVerb True ;
|
||||||
|
NegV = predVerb False ;
|
||||||
|
PosA = predAdjective True ;
|
||||||
|
NegA = predAdjective False ;
|
||||||
|
PosCN = predCommNoun True ;
|
||||||
|
NegCN = predCommNoun False ;
|
||||||
|
PosTV = complTransVerb True ;
|
||||||
|
NegTV = complTransVerb False ;
|
||||||
|
PosNP = predNounPhrase True ;
|
||||||
|
NegNP = predNounPhrase False ;
|
||||||
|
PosVS = complSentVerb True ;
|
||||||
|
NegVS = complSentVerb False ;
|
||||||
|
|
||||||
|
|
||||||
|
AdvVP = adVerbPhrase ;
|
||||||
|
LocNP = locativeNounPhrase ;
|
||||||
|
AdvCN = advCommNounPhrase ;
|
||||||
|
|
||||||
|
PosSlashTV = slashTransVerb True ;
|
||||||
|
NegSlashTV = slashTransVerb False ;
|
||||||
|
|
||||||
|
IdRP = identRelPron ;
|
||||||
|
FunRP = funRelPron ;
|
||||||
|
RelVP = relVerbPhrase ;
|
||||||
|
RelSlash = relSlash ;
|
||||||
|
ModRC = modRelClause ;
|
||||||
|
RelSuch = relSuch ;
|
||||||
|
|
||||||
|
WhoOne = intPronWho singular ;
|
||||||
|
WhoMany = intPronWho plural ;
|
||||||
|
WhatOne = intPronWhat singular ;
|
||||||
|
WhatMany = intPronWhat plural ;
|
||||||
|
FunIP = funIntPron ;
|
||||||
|
NounIPOne = nounIntPron singular ;
|
||||||
|
NounIPMany = nounIntPron plural ;
|
||||||
|
|
||||||
|
QuestVP = questVerbPhrase ;
|
||||||
|
IntVP = intVerbPhrase ;
|
||||||
|
IntSlash = intSlash ;
|
||||||
|
QuestAdv = questAdverbial ;
|
||||||
|
|
||||||
|
ImperVP = imperVerbPhrase ;
|
||||||
|
|
||||||
|
IndicPhrase = indicUtt ;
|
||||||
|
QuestPhrase = interrogUtt ;
|
||||||
|
ImperOne = imperUtterance singular ;
|
||||||
|
ImperMany = imperUtterance plural ;
|
||||||
|
|
||||||
|
lin
|
||||||
|
TwoS = twoSentence ;
|
||||||
|
ConsS = consSentence ;
|
||||||
|
ConjS = conjunctSentence ;
|
||||||
|
ConjDS = conjunctDistrSentence ;
|
||||||
|
|
||||||
|
TwoAP = twoAdjPhrase ;
|
||||||
|
ConsAP = consAdjPhrase ;
|
||||||
|
ConjAP = conjunctAdjPhrase ;
|
||||||
|
ConjDAP = conjunctDistrAdjPhrase ;
|
||||||
|
|
||||||
|
TwoNP = twoNounPhrase ;
|
||||||
|
ConsNP = consNounPhrase ;
|
||||||
|
ConjNP = conjunctNounPhrase ;
|
||||||
|
ConjDNP = conjunctDistrNounPhrase ;
|
||||||
|
|
||||||
|
SubjS = subjunctSentence ;
|
||||||
|
SubjImper = subjunctImperative ;
|
||||||
|
SubjQu = subjunctQuestion ;
|
||||||
|
|
||||||
|
PhrNP = useNounPhrase ;
|
||||||
|
PhrOneCN = useCommonNounPhrase singular ;
|
||||||
|
PhrManyCN = useCommonNounPhrase plural ;
|
||||||
|
PhrIP ip = ip ;
|
||||||
|
PhrIAdv ia = ia ;
|
||||||
|
|
||||||
|
INP = pronNounPhrase jag_32 ;
|
||||||
|
ThouNP = pronNounPhrase du_33 ;
|
||||||
|
HeNP = pronNounPhrase han_34 ;
|
||||||
|
SheNP = pronNounPhrase hon_35 ;
|
||||||
|
WeNP = pronNounPhrase vi_36 ;
|
||||||
|
YeNP = pronNounPhrase ni_37 ;
|
||||||
|
TheyNP = pronNounPhrase de_38 ;
|
||||||
|
|
||||||
|
YouNP = let {ni = pronNounPhrase ni_37 } in {s = ni.s ; g = ni.g ; n = Sg} ;
|
||||||
|
|
||||||
|
EveryDet = varjeDet ;
|
||||||
|
AllDet = allaDet ;
|
||||||
|
WhichDet = vilkenDet ;
|
||||||
|
MostDet = flestaDet ;
|
||||||
|
|
||||||
|
HowIAdv = ss "hur" ;
|
||||||
|
WhenIAdv = ss "när" ;
|
||||||
|
WhereIAdv = ss "var" ;
|
||||||
|
WhyIAdv = ss "varför" ;
|
||||||
|
|
||||||
|
AndConj = ss "och" ** {n = Pl} ;
|
||||||
|
OrConj = ss "eller" ** {n = Sg} ;
|
||||||
|
BothAnd = sd2 "både" "och" ** {n = Pl} ;
|
||||||
|
EitherOr = sd2 "antingen" "eller" ** {n = Sg} ;
|
||||||
|
NeitherNor = sd2 "varken" "eller" ** {n = Sg} ;
|
||||||
|
IfSubj = ss "om" ;
|
||||||
|
WhenSubj = ss "när" ;
|
||||||
|
|
||||||
|
PhrYes = ss ["Ja ."] ;
|
||||||
|
PhrNo = ss ["Nej ."] ;
|
||||||
|
} ;
|
||||||
1
grammars/resource/swedish/Svenska.gf
Normal file
1
grammars/resource/swedish/Svenska.gf
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resource Svenska = reuse ResSwe ;
|
||||||
1000
grammars/resource/swedish/Syntax.gf
Normal file
1000
grammars/resource/swedish/Syntax.gf
Normal file
File diff suppressed because it is too large
Load Diff
35
grammars/resource/swedish/TestSwe.gf
Normal file
35
grammars/resource/swedish/TestSwe.gf
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
concrete TestSwe of TestAbs = ResSwe ** open Syntax in {
|
||||||
|
|
||||||
|
flags startcat=Phr ; lexer=text ; parser=chart ; unlexer=text ;
|
||||||
|
|
||||||
|
-- a random sample from the lexicon
|
||||||
|
|
||||||
|
lin
|
||||||
|
Big = stor_25 ;
|
||||||
|
Small = liten_1146 ;
|
||||||
|
Old = gammal_16 ;
|
||||||
|
Young = ung_29 ;
|
||||||
|
Man = extCommNoun Masc man_1144 ;
|
||||||
|
Woman = extCommNoun NoMasc (sApa "kvinn") ;
|
||||||
|
Car = extCommNoun NoMasc (sBil "bil") ;
|
||||||
|
House = extCommNoun NoMasc (sHus "hus") ;
|
||||||
|
Light = extCommNoun NoMasc (sHus "ljus") ;
|
||||||
|
Walk = extVerb Act gå_1174 ;
|
||||||
|
Run = extVerb Act (vFinna "spring" "sprang" "sprung") ;
|
||||||
|
Love = extTransVerb (vTala "älsk") [] ;
|
||||||
|
Send = extTransVerb (vTala "skick") [] ;
|
||||||
|
Wait = extTransVerb (vTala "vänt") "på" ;
|
||||||
|
Say = extVerb Act (vLeka "säg") ; --- works in present tense...
|
||||||
|
Prove = extVerb Act (vTala "bevis") ;
|
||||||
|
SwitchOn = extTransVerb (vVända "tän") [] ;
|
||||||
|
SwitchOff = extTransVerb (vLeka "släck") [] ;
|
||||||
|
|
||||||
|
Mother = mkFun (extCommNoun NoMasc mor_1) "till" ;
|
||||||
|
Uncle = mkFun (extCommNoun Masc farbror_8) "till" ;
|
||||||
|
|
||||||
|
Always = advPre "alltid" ;
|
||||||
|
Well = advPost "bra" ;
|
||||||
|
|
||||||
|
John = mkProperName "Johan" Utr Masc ;
|
||||||
|
Mary = mkProperName "Maria" Utr NoMasc ;
|
||||||
|
} ;
|
||||||
150
grammars/resource/swedish/Types.gf
Normal file
150
grammars/resource/swedish/Types.gf
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
--1 Swedish Word Classes and Morphological Parameters
|
||||||
|
--
|
||||||
|
-- This is a resource module for Swedish morphology, defining the
|
||||||
|
-- morphological parameters and word classes of Swedish. It is aimed
|
||||||
|
-- to be complete w.r.t. the description of word forms.
|
||||||
|
-- However, it does not include those parameters that are not needed for
|
||||||
|
-- analysing individual words: such parameters are defined in syntax modules.
|
||||||
|
--
|
||||||
|
-- This GF grammar was obtained from the functional morphology file TypesSw.hs
|
||||||
|
-- semi-automatically. The GF inflection engine obtained was obtained automatically.
|
||||||
|
|
||||||
|
resource Types = open Prelude in {
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
--2 Enumerated parameter types
|
||||||
|
--
|
||||||
|
-- These types are the ones found in school grammars.
|
||||||
|
-- Their parameter values are atomic.
|
||||||
|
|
||||||
|
param
|
||||||
|
Gender = Utr | Neutr ;
|
||||||
|
Number = Sg | Pl ;
|
||||||
|
Species = Indef | Def ;
|
||||||
|
Case = Nom | Gen ;
|
||||||
|
Sex = NoMasc | Masc ;
|
||||||
|
Mode = Ind | Cnj ;
|
||||||
|
Voice = Act | Pass ;
|
||||||
|
Degree = Pos | Comp | Sup ;
|
||||||
|
Person = P1 | P2 | P3 ;
|
||||||
|
|
||||||
|
--2 Word classes and hierarchical parameter types
|
||||||
|
--
|
||||||
|
-- Real parameter types (i.e. ones on which words and phrases depend)
|
||||||
|
-- are mostly hierarchical. The alternative would be cross-products of
|
||||||
|
-- simple parameters, but this would usually overgenerate.
|
||||||
|
--
|
||||||
|
|
||||||
|
--3 Substantives
|
||||||
|
--
|
||||||
|
-- Substantives (= common nouns) have a parameter of type SubstForm.
|
||||||
|
|
||||||
|
param SubstForm = SF Number Species Case ;
|
||||||
|
|
||||||
|
-- Substantives moreover have an inherent gender.
|
||||||
|
|
||||||
|
oper Subst : Type = {s : SubstForm => Str ; h1 : Gender} ;
|
||||||
|
|
||||||
|
--3 Adjectives
|
||||||
|
--
|
||||||
|
-- Adjectives are a very complex class, and the full table has as many as
|
||||||
|
-- 18 different forms. The major division is between the comparison degrees;
|
||||||
|
-- the comparative has only the 2 case forms, whereas the positive has 12 forms.
|
||||||
|
|
||||||
|
param
|
||||||
|
AdjForm = AF AdjFormGrad Case ;
|
||||||
|
|
||||||
|
-- The positive strong forms depend on gender: "en stor bil" - "ett stort hus".
|
||||||
|
-- But the weak forms depend on sex: "den stora bilen" - "den store mannen".
|
||||||
|
-- The plural never makes a gender-sex distinction.
|
||||||
|
|
||||||
|
GenNum = ASg Gender | APl ;
|
||||||
|
SexNum = AxSg Sex | AxPl ;
|
||||||
|
|
||||||
|
AdjFormPos = Strong GenNum | Weak SexNum ;
|
||||||
|
AdjFormSup = SupStrong | SupWeak ;
|
||||||
|
|
||||||
|
AdjFormGrad =
|
||||||
|
Posit AdjFormPos
|
||||||
|
| Compar
|
||||||
|
| Super AdjFormSup ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
Adj : Type = {s : AdjForm => Str} ;
|
||||||
|
|
||||||
|
--3 Verbs
|
||||||
|
--
|
||||||
|
-- Verbs have 9 finite forms and as many as 18 infinite forms; the large number
|
||||||
|
-- of the latter comes from adjectives.
|
||||||
|
|
||||||
|
oper Verbum : Type = {s : VerbForm => Str} ;
|
||||||
|
|
||||||
|
param
|
||||||
|
VFin =
|
||||||
|
Pres Mode Voice
|
||||||
|
| Pret Mode Voice
|
||||||
|
| Imper ; --- no passive
|
||||||
|
|
||||||
|
VInf =
|
||||||
|
Inf Voice
|
||||||
|
| Supin Voice
|
||||||
|
| PtPres Case
|
||||||
|
| PtPret AdjFormPos Case ;
|
||||||
|
|
||||||
|
VerbForm =
|
||||||
|
VF VFin
|
||||||
|
| VI VInf ;
|
||||||
|
|
||||||
|
-- However, the syntax only needs a simplified verb category, with
|
||||||
|
-- present tense only. Such a verb can be extracted from the full verb,
|
||||||
|
-- and a choice can be made between an active and a passive (deponent) verb.
|
||||||
|
|
||||||
|
param
|
||||||
|
VForm = Infinit | Indicat | Imperat ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
Verb : Type = SS1 VForm ;
|
||||||
|
|
||||||
|
extVerb : Voice -> Verbum -> Verb = \v,verb -> {s = table {
|
||||||
|
Infinit => verb.s ! VI (Inf v) ;
|
||||||
|
Indicat => verb.s ! VF (Pres Ind v) ;
|
||||||
|
Imperat => verb.s ! VF Imper --- no passive in Verbum
|
||||||
|
}} ;
|
||||||
|
|
||||||
|
--3 Other open classes
|
||||||
|
--
|
||||||
|
-- Proper names, adverbs (Adv having comparison forms and AdvIn not having them),
|
||||||
|
-- and interjections are the remaining open classes.
|
||||||
|
|
||||||
|
oper
|
||||||
|
PNm : Type = {s : Case => Str ; h1 : Gender} ;
|
||||||
|
Adv : Type = {s : Degree => Str} ;
|
||||||
|
AdvInv : Type = {s : Str} ;
|
||||||
|
Interj : Type = {s : Str} ;
|
||||||
|
|
||||||
|
--3 Closed classes
|
||||||
|
--
|
||||||
|
-- The rest of the Swedish word classes are closed, i.e. not extensible by new
|
||||||
|
-- lexical entries. Thus we don't have to know how to build them, but only
|
||||||
|
-- how to use them, i.e. which parameters they have.
|
||||||
|
--
|
||||||
|
-- The most important distinction is between proper-name-like pronouns and
|
||||||
|
-- adjective-like pronouns, which are inflected in completely different parameters.
|
||||||
|
|
||||||
|
param
|
||||||
|
NPForm = PNom | PAcc | PGen GenNum ;
|
||||||
|
AdjPronForm = APron GenNum Case ;
|
||||||
|
AuxVerbForm = AuxInf | AuxPres | AuxPret | AuxSup ;
|
||||||
|
|
||||||
|
oper
|
||||||
|
ProPN : Type = {s : NPForm => Str ; h1 : Gender ; h2 : Number ; h3 : Person} ;
|
||||||
|
ProAdj : Type = {s : AdjPronForm => Str} ;
|
||||||
|
Prep : Type = {s : Str} ;
|
||||||
|
Conjunct : Type = {s : Str} ;
|
||||||
|
Subjunct : Type = {s : Str} ;
|
||||||
|
Art : Type = {s : GenNum => Str} ;
|
||||||
|
Part : Type = {s : Str} ;
|
||||||
|
Infin : Type = {s : Str} ;
|
||||||
|
VAux : Type = {s : AuxVerbForm => Str} ;
|
||||||
|
}
|
||||||
78
src/GF.hs
Normal file
78
src/GF.hs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import UseIO
|
||||||
|
import Option
|
||||||
|
import IOGrammar
|
||||||
|
import ShellState
|
||||||
|
import Shell
|
||||||
|
import SubShell
|
||||||
|
import PShell
|
||||||
|
import JGF
|
||||||
|
import UTF8
|
||||||
|
|
||||||
|
import Today (today)
|
||||||
|
import Arch
|
||||||
|
import System (getArgs)
|
||||||
|
|
||||||
|
-- AR 19/4/2000 -- 11/11/2001
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
xs <- getArgs
|
||||||
|
let (os,fs) = getOptions "-" xs
|
||||||
|
java = oElem forJava os
|
||||||
|
putStrLn $ if java then encodeUTF8 welcomeMsg else welcomeMsg
|
||||||
|
st <- case fs of
|
||||||
|
f:_ -> useIOE emptyShellState (shellStateFromFiles os emptyShellState f)
|
||||||
|
_ -> return emptyShellState
|
||||||
|
if null fs then return () else putCPU
|
||||||
|
if java then sessionLineJ st else do
|
||||||
|
gfInteract (initHState st)
|
||||||
|
return ()
|
||||||
|
|
||||||
|
gfInteract :: HState -> IO HState
|
||||||
|
gfInteract st@(env,_) = do
|
||||||
|
-- putStrFlush "> " M.F 25/01-02 prompt moved to Arch.
|
||||||
|
(s,cs) <- getCommandLines
|
||||||
|
case ifImpure cs of
|
||||||
|
|
||||||
|
-- these are the three impure commands
|
||||||
|
Just (ICQuit,_) -> do
|
||||||
|
putStrLn "See you."
|
||||||
|
return st
|
||||||
|
Just (ICExecuteHistory file,_) -> do
|
||||||
|
ss <- readFileIf file
|
||||||
|
let co = pCommandLines ss
|
||||||
|
st' <- execLinesH s co st
|
||||||
|
gfInteract st'
|
||||||
|
Just (ICEarlierCommand i,_) -> do
|
||||||
|
let line = earlierCommandH st i
|
||||||
|
co = pCommandLine $ words line
|
||||||
|
st' <- execLinesH line [co] st -- s would not work in execLinesH
|
||||||
|
gfInteract st'
|
||||||
|
Just (ICEditSession,os) ->
|
||||||
|
editSession (addOptions os opts) env >> gfInteract st
|
||||||
|
{- -----
|
||||||
|
Just (ICTranslateSession,os) ->
|
||||||
|
translateSession (addOptions os opts) env >> gfInteract st
|
||||||
|
-}
|
||||||
|
-- this is a normal command sequence
|
||||||
|
_ -> do
|
||||||
|
st' <- execLinesH s cs st
|
||||||
|
gfInteract st'
|
||||||
|
where
|
||||||
|
opts = globalOptions env
|
||||||
|
|
||||||
|
welcomeMsg =
|
||||||
|
"Welcome to " ++ authorMsg ++++ welcomeArch ++ "\n\nType 'h' for help."
|
||||||
|
|
||||||
|
authorMsg = unlines [
|
||||||
|
"Grammatical Framework, Version 2.0-- (incomplete functionality)",
|
||||||
|
--- "Compiled March 26, 2003",
|
||||||
|
"Compiled " ++ today,
|
||||||
|
"Copyright (c) Markus Forsberg, Thomas Hallgren, Kristofer Johannisson,",
|
||||||
|
"Janna Khegai, Peter Ljunglöf, Petri Mäenpää, and Aarne Ranta",
|
||||||
|
"1998-2003, under GNU General Public License (GPL)",
|
||||||
|
"Bug reports to aarne@cs.chalmers.se"
|
||||||
|
]
|
||||||
267
src/GF/API.hs
Normal file
267
src/GF/API.hs
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
module API where
|
||||||
|
|
||||||
|
import qualified AbsGF as GF
|
||||||
|
import qualified AbsGFC as A
|
||||||
|
import qualified Rename as R
|
||||||
|
import GetTree
|
||||||
|
import GFC
|
||||||
|
import Values
|
||||||
|
|
||||||
|
-----import GetGrammar
|
||||||
|
-----import Compile
|
||||||
|
import IOGrammar
|
||||||
|
import Linear
|
||||||
|
import Parsing
|
||||||
|
import Morphology
|
||||||
|
import PPrCF
|
||||||
|
import CFIdent
|
||||||
|
import PGrammar
|
||||||
|
import Randomized (mkRandomTree)
|
||||||
|
import Zipper
|
||||||
|
|
||||||
|
import MMacros
|
||||||
|
import TypeCheck
|
||||||
|
import CMacros
|
||||||
|
|
||||||
|
import Option
|
||||||
|
import Custom
|
||||||
|
import ShellState
|
||||||
|
import Linear
|
||||||
|
import GFC
|
||||||
|
import qualified Grammar as G
|
||||||
|
import PrGrammar
|
||||||
|
import qualified Compute as Co
|
||||||
|
import qualified Ident as I
|
||||||
|
import qualified GrammarToCanon as GC
|
||||||
|
import qualified CanonToGrammar as CG
|
||||||
|
|
||||||
|
import Editing
|
||||||
|
|
||||||
|
----import GrammarToXML
|
||||||
|
|
||||||
|
----import GrammarToMGrammar as M
|
||||||
|
|
||||||
|
import Arch (myStdGen)
|
||||||
|
|
||||||
|
import UTF8
|
||||||
|
import Operations
|
||||||
|
import UseIO
|
||||||
|
|
||||||
|
import List (nub)
|
||||||
|
import Monad (liftM)
|
||||||
|
import System (system)
|
||||||
|
|
||||||
|
-- Application Programmer's Interface to GF; also used by Shell. AR 10/11/2001
|
||||||
|
|
||||||
|
type GFGrammar = StateGrammar
|
||||||
|
type GFCat = CFCat
|
||||||
|
type Ident = I.Ident
|
||||||
|
|
||||||
|
-- these are enough for many simple applications
|
||||||
|
|
||||||
|
{- -----
|
||||||
|
file2grammar :: FilePath -> IO GFGrammar
|
||||||
|
file2grammar = do
|
||||||
|
egr <- appIOE $ optFile2grammar (iOpts [beSilent])
|
||||||
|
err putStrLn return egr
|
||||||
|
-}
|
||||||
|
|
||||||
|
linearize :: GFGrammar -> Tree -> String
|
||||||
|
linearize sgr = err id id . optLinearizeTree opts sgr where
|
||||||
|
opts = addOption firstLin $ stateOptions sgr
|
||||||
|
|
||||||
|
linearizeToAll :: [GFGrammar] -> Tree -> [String]
|
||||||
|
linearizeToAll grs t = [linearize gr t | gr <- grs]
|
||||||
|
|
||||||
|
parse :: GFGrammar -> CFCat -> String -> [Tree]
|
||||||
|
parse sgr cat = errVal [] . parseString noOptions sgr cat
|
||||||
|
|
||||||
|
parseAny :: [GFGrammar] -> CFCat -> String -> [Tree]
|
||||||
|
parseAny grs cat s = concat [parse gr cat s | gr <- grs]
|
||||||
|
|
||||||
|
translate :: GFGrammar -> GFGrammar -> CFCat -> String -> [String]
|
||||||
|
translate ig og cat = map (linearize og) . parse ig cat
|
||||||
|
|
||||||
|
translateToAll :: GFGrammar -> [GFGrammar] -> CFCat -> String -> [String]
|
||||||
|
translateToAll ig ogs cat = concat . map (linearizeToAll ogs) . parse ig cat
|
||||||
|
|
||||||
|
translateFromAny :: [GFGrammar] -> GFGrammar -> CFCat -> String -> [String]
|
||||||
|
translateFromAny igs og cat s = concat [translate ig og cat s | ig <- igs]
|
||||||
|
|
||||||
|
translateBetweenAll :: [GFGrammar] -> CFCat -> String -> [String]
|
||||||
|
translateBetweenAll grs cat = concat . map (linearizeToAll grs) . parseAny grs cat
|
||||||
|
|
||||||
|
homonyms :: GFGrammar -> CFCat -> Tree -> [Tree]
|
||||||
|
homonyms gr cat = nub . parse gr cat . linearize gr
|
||||||
|
|
||||||
|
hasAmbiguousLin :: GFGrammar -> CFCat -> Tree -> Bool
|
||||||
|
hasAmbiguousLin gr cat t = case (homonyms gr cat t) of
|
||||||
|
_:_:_ -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
-- returns printname if one exists; othewrise linearizes with metas
|
||||||
|
printOrLin :: GFGrammar -> Fun -> String
|
||||||
|
printOrLin gr = printOrLinearize (stateGrammarST gr)
|
||||||
|
|
||||||
|
-- reads a syntax file and writes it in a format wanted
|
||||||
|
transformGrammarFile :: Options -> FilePath -> IO String
|
||||||
|
transformGrammarFile opts file = do
|
||||||
|
sy <- useIOE GF.emptySyntax $ getSyntax opts file
|
||||||
|
return $ optPrintSyntax opts sy
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- then stg for customizable and internal use
|
||||||
|
|
||||||
|
{- -----
|
||||||
|
optFile2grammar :: Options -> FilePath -> IOE GFGrammar
|
||||||
|
optFile2grammar os f = do
|
||||||
|
gr <- ioeErr $ compileModule os f
|
||||||
|
return $ grammar2stateGrammar gr
|
||||||
|
|
||||||
|
optFile2grammarE :: Options -> FilePath -> IOE GFGrammar
|
||||||
|
optFile2grammarE = optFile2grammar
|
||||||
|
-}
|
||||||
|
|
||||||
|
string2treeInState :: GFGrammar -> String -> State -> Err Tree
|
||||||
|
string2treeInState gr s st = do
|
||||||
|
let metas = allMetas st
|
||||||
|
t <- pTerm s
|
||||||
|
annotate (grammar gr) $ qualifTerm (absId gr) $ refreshMetas metas t
|
||||||
|
|
||||||
|
string2srcTerm :: G.SourceGrammar -> I.Ident -> String -> Err G.Term
|
||||||
|
string2srcTerm gr m s = do
|
||||||
|
t <- pTerm s
|
||||||
|
R.renameSourceTerm gr m t
|
||||||
|
|
||||||
|
randomTreesIO :: Options -> GFGrammar -> Int -> IO [Tree]
|
||||||
|
randomTreesIO opts gr n = do
|
||||||
|
gen <- myStdGen mx
|
||||||
|
t <- err (\s -> putStrLnFlush s >> return []) (return . singleton) $
|
||||||
|
mkRandomTree gen mx g cat
|
||||||
|
ts <- if n==1 then return [] else randomTreesIO opts gr (n-1)
|
||||||
|
return $ t ++ ts
|
||||||
|
where
|
||||||
|
cat = firstAbsCat opts gr
|
||||||
|
g = grammar gr
|
||||||
|
mx = optIntOrN opts flagDepth 41
|
||||||
|
|
||||||
|
speechGenerate :: Options -> String -> IO ()
|
||||||
|
speechGenerate opts str = do
|
||||||
|
let lan = maybe "" (" --language" +++) $ getOptVal opts speechLanguage
|
||||||
|
system ("echo" +++ "\"" ++ str ++ "\" | festival --tts" ++ lan)
|
||||||
|
return ()
|
||||||
|
|
||||||
|
optLinearizeTreeVal :: Options -> GFGrammar -> Tree -> String
|
||||||
|
optLinearizeTreeVal opts gr = err id id . optLinearizeTree opts gr
|
||||||
|
|
||||||
|
optLinearizeTree :: Options -> GFGrammar -> Tree -> Err String
|
||||||
|
optLinearizeTree opts gr t
|
||||||
|
| oElem showRecord opts = liftM prt $ linearizeNoMark g c t
|
||||||
|
| otherwise = return $ linTree2string g c t
|
||||||
|
where
|
||||||
|
g = grammar gr
|
||||||
|
c = cncId gr
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
untoksl . lin where
|
||||||
|
gr = concreteOf (stateGrammarST sgr)
|
||||||
|
lin -- options mutually exclusive, with priority: struct, rec, table, one
|
||||||
|
| oElem showStruct opts = markedLinString True gr . tree2loc
|
||||||
|
| oElem showRecord opts = err id prt . linTerm gr
|
||||||
|
| oElem tableLin opts = err id (concatMap prLinTable) . allLinsAsStrs gr
|
||||||
|
| oElem firstLin opts = unlines . map sstr . take 1 . allLinStrings gr
|
||||||
|
| otherwise = unlines . map sstr . optIntOrAll opts flagNumber . allLinStrings gr
|
||||||
|
untoks = customOrDefault opts' useUntokenizer customUntokenizer sgr
|
||||||
|
opts' = addOptions opts $ stateOptions sgr
|
||||||
|
untoksl = unlines . map untoks . lines
|
||||||
|
-}
|
||||||
|
|
||||||
|
{-
|
||||||
|
optLinearizeArgForm :: Options -> StateGrammar -> [Term] -> Term -> String
|
||||||
|
optLinearizeArgForm opts sgr fs ts0 = untoksl $ lin ts where
|
||||||
|
gr = concreteOf (stateGrammarST sgr)
|
||||||
|
ts = annotateTrm sgr ts0
|
||||||
|
ms = map (renameTrm (lookupConcrete gr)) fs
|
||||||
|
lin -- options mutually exclusive, with priority: struct, rec, table
|
||||||
|
| oElem tableLin opts = err id (concatMap prLinTable) . allLinsForForms gr ms
|
||||||
|
| otherwise = err id (unlines . map sstr . tkStrs . concat) . allLinsForForms gr ms
|
||||||
|
tkStrs = concat . map snd . concat . map snd
|
||||||
|
untoks = customOrDefault opts' useUntokenizer customUntokenizer sgr
|
||||||
|
opts' = addOptions opts $ stateOptions sgr
|
||||||
|
untoksl = unlines . map untoks . lines
|
||||||
|
-}
|
||||||
|
|
||||||
|
optParseArg :: Options -> GFGrammar -> String -> [Tree]
|
||||||
|
optParseArg opts gr = err (const []) id . optParseArgErr opts gr
|
||||||
|
|
||||||
|
optParseArgErr :: Options -> GFGrammar -> String -> Err [Tree]
|
||||||
|
optParseArgErr opts gr = liftM fst . optParseArgErrMsg opts gr
|
||||||
|
|
||||||
|
optParseArgErrMsg :: Options -> GFGrammar -> String -> Err ([Tree],String)
|
||||||
|
optParseArgErrMsg opts gr s =
|
||||||
|
let cat = firstCatOpts opts gr
|
||||||
|
in parseStringMsg opts gr cat s
|
||||||
|
|
||||||
|
-- analyses word by word
|
||||||
|
morphoAnalyse :: Options -> GFGrammar -> String -> String
|
||||||
|
morphoAnalyse opts gr
|
||||||
|
| oElem beShort opts = morphoTextShort mo
|
||||||
|
| otherwise = morphoText mo
|
||||||
|
where
|
||||||
|
mo = morpho gr
|
||||||
|
|
||||||
|
{-
|
||||||
|
prExpXML :: StateGrammar -> Term -> [String]
|
||||||
|
prExpXML gr = prElementX . term2elemx (stateAbstract gr)
|
||||||
|
|
||||||
|
prMultiGrammar :: Options -> ShellState -> String
|
||||||
|
prMultiGrammar opts = M.showMGrammar (oElem optimizeCanon opts)
|
||||||
|
-}
|
||||||
|
-- access to customizable commands
|
||||||
|
|
||||||
|
optPrintGrammar :: Options -> StateGrammar -> String
|
||||||
|
optPrintGrammar opts = customOrDefault opts grammarPrinter customGrammarPrinter
|
||||||
|
|
||||||
|
optPrintSyntax :: Options -> GF.Grammar -> String
|
||||||
|
optPrintSyntax opts = customOrDefault opts grammarPrinter customSyntaxPrinter
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
optPrintTree :: Options -> GFGrammar -> Tree -> String
|
||||||
|
optPrintTree opts = customOrDefault opts grammarPrinter customTermPrinter
|
||||||
|
|
||||||
|
-- look for string command (-filter=x)
|
||||||
|
optStringCommand :: Options -> GFGrammar -> String -> String
|
||||||
|
optStringCommand opts g =
|
||||||
|
optIntOrAll opts flagLength .
|
||||||
|
customOrDefault opts filterString customStringCommand g
|
||||||
|
|
||||||
|
optTreeCommand :: Options -> GFGrammar -> Tree -> [Tree]
|
||||||
|
optTreeCommand opts st =
|
||||||
|
optIntOrAll opts flagNumber .
|
||||||
|
customOrDefault opts termCommand customTermCommand st
|
||||||
|
-}
|
||||||
|
|
||||||
|
{-
|
||||||
|
-- wraps term in a function and optionally computes the result
|
||||||
|
|
||||||
|
wrapByFun :: Options -> StateGrammar -> Ident -> Term -> Term
|
||||||
|
wrapByFun opts g f t =
|
||||||
|
if oElem doCompute opts
|
||||||
|
then err (const t) id $ computeAbsTerm (stateAbstract g) (appCons f [t])
|
||||||
|
else appCons f [t]
|
||||||
|
|
||||||
|
optTransfer :: Options -> StateGrammar -> Term -> Term
|
||||||
|
optTransfer opts g = case getOptVal opts transferFun of
|
||||||
|
Just f -> wrapByFun (addOption doCompute opts) g (string2id f)
|
||||||
|
_ -> id
|
||||||
|
-}
|
||||||
|
optTokenizer :: Options -> GFGrammar -> String -> String
|
||||||
|
optTokenizer opts gr = show . customOrDefault opts useTokenizer customTokenizer gr
|
||||||
|
|
||||||
|
-- performs UTF8 if the language name is not *U.gf ; should be by gr option ---
|
||||||
|
optEncodeUTF8 :: Language -> GFGrammar -> String -> String
|
||||||
|
optEncodeUTF8 lang gr = case reverse (prLanguage lang) of
|
||||||
|
'U':_ -> id
|
||||||
|
_ -> encodeUTF8
|
||||||
|
|
||||||
42
src/GF/API/IOGrammar.hs
Normal file
42
src/GF/API/IOGrammar.hs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
module IOGrammar where
|
||||||
|
|
||||||
|
import Option
|
||||||
|
import Abstract
|
||||||
|
import qualified GFC
|
||||||
|
import PGrammar
|
||||||
|
import TypeCheck
|
||||||
|
import Compile
|
||||||
|
import ShellState
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import UseIO
|
||||||
|
import Arch
|
||||||
|
|
||||||
|
import Monad (liftM)
|
||||||
|
|
||||||
|
-- for reading grammars and terms from strings and files
|
||||||
|
|
||||||
|
--- a heuristic way of renaming constants is used
|
||||||
|
string2absTerm :: String -> String -> Term
|
||||||
|
string2absTerm m = renameTermIn m . pTrm
|
||||||
|
|
||||||
|
renameTermIn :: String -> Term -> Term
|
||||||
|
renameTermIn m = refreshMetas [] . rename [] where
|
||||||
|
rename vs t = case t of
|
||||||
|
Abs x b -> Abs x (rename (x:vs) b)
|
||||||
|
Vr c -> if elem c vs then t else Q (zIdent m) c
|
||||||
|
App f a -> App (rename vs f) (rename vs a)
|
||||||
|
_ -> t
|
||||||
|
|
||||||
|
string2annotTree :: GFC.CanonGrammar -> Ident -> String -> Err Tree
|
||||||
|
string2annotTree gr m = annotate gr . string2absTerm (prt m) ---- prt
|
||||||
|
|
||||||
|
----string2paramList :: ConcreteST -> String -> [Term]
|
||||||
|
---string2paramList st = map (renameTrm (lookupConcrete st) . patt2term) . pPattList
|
||||||
|
|
||||||
|
shellStateFromFiles :: Options -> ShellState -> FilePath -> IOE ShellState
|
||||||
|
shellStateFromFiles opts st file = do
|
||||||
|
let osb = addOptions (options [beVerbose, emitCode]) opts ---
|
||||||
|
grts <- compileModule osb st file
|
||||||
|
ioeErr $ updateShellState opts st grts
|
||||||
|
--- liftM (changeModTimes rts) $ grammar2shellState opts gr
|
||||||
180
src/GF/CF/CF.hs
Normal file
180
src/GF/CF/CF.hs
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
module CF where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Str
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
import CFIdent
|
||||||
|
import List (nub,nubBy)
|
||||||
|
import Char (isUpper, isLower, toUpper, toLower)
|
||||||
|
|
||||||
|
-- context-free grammars. AR 15/12/1999 -- 30/3/2000 -- 2/6/2001 -- 3/12/2001
|
||||||
|
|
||||||
|
-- CF grammar data types
|
||||||
|
|
||||||
|
-- abstract type CF.
|
||||||
|
-- Invariant: each category has all its rules grouped with it
|
||||||
|
-- also: the list is never empty (the category is just missing then)
|
||||||
|
newtype CF = CF ([(CFCat,[CFRule])], CFPredef)
|
||||||
|
type CFRule = (CFFun, (CFCat, [CFItem]))
|
||||||
|
|
||||||
|
-- CFPredef is a hack for variable symbols and literals; normally = const []
|
||||||
|
data CFItem = CFTerm RegExp | CFNonterm CFCat deriving (Eq, Ord,Show)
|
||||||
|
|
||||||
|
newtype CFTree = CFTree (CFFun,(CFCat, [CFTree])) deriving (Eq, Show)
|
||||||
|
|
||||||
|
type CFPredef = CFTok -> [(CFCat, CFFun)] -- recognize literals, variables, etc
|
||||||
|
|
||||||
|
-- Wadler style + return information
|
||||||
|
type CFParser = [CFTok] -> ([(CFTree,[CFTok])],String)
|
||||||
|
|
||||||
|
cfParseResults :: ([(CFTree,[CFTok])],String) -> [CFTree]
|
||||||
|
cfParseResults rs = [b | (b,[]) <- fst rs]
|
||||||
|
|
||||||
|
-- terminals are regular expressions on words; to be completed to full regexp
|
||||||
|
data RegExp =
|
||||||
|
RegAlts [CFWord] -- list of alternative words
|
||||||
|
| RegSpec CFTok -- special token
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
type CFWord = String
|
||||||
|
|
||||||
|
-- the above types should be kept abstract, and the following functions used
|
||||||
|
|
||||||
|
-- to construct CF grammars
|
||||||
|
|
||||||
|
emptyCF :: CF
|
||||||
|
emptyCF = CF ([], emptyCFPredef)
|
||||||
|
|
||||||
|
emptyCFPredef :: CFPredef
|
||||||
|
emptyCFPredef = const []
|
||||||
|
|
||||||
|
rules2CF :: [CFRule] -> CF
|
||||||
|
rules2CF rs = CF (groupCFRules rs, emptyCFPredef)
|
||||||
|
|
||||||
|
groupCFRules :: [CFRule] -> [(CFCat,[CFRule])]
|
||||||
|
groupCFRules = foldr ins [] where
|
||||||
|
ins rule crs = case crs of
|
||||||
|
(c,r) : rs | compatCF c cat -> (c,rule:r) : rs
|
||||||
|
cr : rs -> cr : ins rule rs
|
||||||
|
_ -> [(cat,[rule])]
|
||||||
|
where
|
||||||
|
cat = valCatCF rule
|
||||||
|
|
||||||
|
-- to construct rules
|
||||||
|
|
||||||
|
-- make a rule from a single token without constituents
|
||||||
|
atomCFRule :: CFCat -> CFFun -> CFTok -> CFRule
|
||||||
|
atomCFRule c f s = (f, (c, [atomCFTerm s]))
|
||||||
|
|
||||||
|
-- usual terminal
|
||||||
|
atomCFTerm :: CFTok -> CFItem
|
||||||
|
atomCFTerm = CFTerm . atomRegExp
|
||||||
|
|
||||||
|
atomRegExp :: CFTok -> RegExp
|
||||||
|
atomRegExp t = case t of
|
||||||
|
TS s -> RegAlts [s]
|
||||||
|
_ -> RegSpec t
|
||||||
|
|
||||||
|
-- terminal consisting of alternatives
|
||||||
|
altsCFTerm :: [String] -> CFItem
|
||||||
|
altsCFTerm = CFTerm . RegAlts
|
||||||
|
|
||||||
|
|
||||||
|
-- to construct trees
|
||||||
|
|
||||||
|
-- make a tree without constituents
|
||||||
|
atomCFTree :: CFCat -> CFFun -> CFTree
|
||||||
|
atomCFTree c f = buildCFTree c f []
|
||||||
|
|
||||||
|
-- make a tree with constituents.
|
||||||
|
buildCFTree :: CFCat -> CFFun -> [CFTree] -> CFTree
|
||||||
|
buildCFTree c f trees = CFTree (f,(c,trees))
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
cfMeta0 :: CFTree
|
||||||
|
cfMeta0 = atomCFTree uCFCat metaCFFun
|
||||||
|
|
||||||
|
-- used in happy
|
||||||
|
litCFTree :: String -> CFTree --- Maybe CFTree
|
||||||
|
litCFTree s = maybe cfMeta0 id $ do
|
||||||
|
(c,f) <- getCFLiteral s
|
||||||
|
return $ buildCFTree c f []
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- to decide whether a token matches a terminal item
|
||||||
|
|
||||||
|
matchCFTerm :: CFItem -> CFTok -> Bool
|
||||||
|
matchCFTerm (CFTerm t) s = satRegExp t s
|
||||||
|
matchCFTerm _ _ = False
|
||||||
|
|
||||||
|
satRegExp :: RegExp -> CFTok -> Bool
|
||||||
|
satRegExp r t = case (r,t) of
|
||||||
|
(RegAlts tt, TS s) -> elem s tt
|
||||||
|
(RegAlts tt, TC s) -> or [elem s' tt | s' <- caseUpperOrLower s]
|
||||||
|
(RegSpec x, _) -> t == x ---
|
||||||
|
_ -> False
|
||||||
|
where
|
||||||
|
caseUpperOrLower s = case s of
|
||||||
|
c:cs | isUpper c -> [s, toLower c : cs]
|
||||||
|
c:cs | isLower c -> [s, toUpper c : cs]
|
||||||
|
_ -> [s]
|
||||||
|
|
||||||
|
-- to analyse a CF grammar
|
||||||
|
|
||||||
|
catsOfCF :: CF -> [CFCat]
|
||||||
|
catsOfCF (CF (rr,_)) = map fst rr
|
||||||
|
|
||||||
|
rulesOfCF :: CF -> [CFRule]
|
||||||
|
rulesOfCF (CF (rr,_)) = concatMap snd rr
|
||||||
|
|
||||||
|
ruleGroupsOfCF :: CF -> [(CFCat,[CFRule])]
|
||||||
|
ruleGroupsOfCF (CF (rr,_)) = rr
|
||||||
|
|
||||||
|
rulesForCFCat :: CF -> CFCat -> [CFRule]
|
||||||
|
rulesForCFCat (CF (rr,_)) cat = maybe [] id $ lookup cat rr
|
||||||
|
|
||||||
|
valCatCF :: CFRule -> CFCat
|
||||||
|
valCatCF (_,(c,_)) = c
|
||||||
|
|
||||||
|
valItemsCF :: CFRule -> [CFItem]
|
||||||
|
valItemsCF (_,(_,i)) = i
|
||||||
|
|
||||||
|
valFunCF :: CFRule -> CFFun
|
||||||
|
valFunCF (f,(_,_)) = f
|
||||||
|
|
||||||
|
startCat :: CF -> CFCat
|
||||||
|
startCat (CF (rr,_)) = fst (head rr) --- hardly useful
|
||||||
|
|
||||||
|
predefOfCF :: CF -> CFPredef
|
||||||
|
predefOfCF (CF (_,f)) = f
|
||||||
|
|
||||||
|
appCFPredef :: CF -> CFTok -> [(CFCat, CFFun)]
|
||||||
|
appCFPredef = ($) . predefOfCF
|
||||||
|
|
||||||
|
valCFItem :: CFItem -> Either RegExp CFCat
|
||||||
|
valCFItem (CFTerm r) = Left r
|
||||||
|
valCFItem (CFNonterm nt) = Right nt
|
||||||
|
|
||||||
|
cfTokens :: CF -> [CFWord]
|
||||||
|
cfTokens cf = nub $ concat $ [ wordsOfRegExp i | r <- rulesOfCF cf,
|
||||||
|
CFTerm i <- valItemsCF r]
|
||||||
|
|
||||||
|
wordsOfRegExp :: RegExp -> [CFWord]
|
||||||
|
wordsOfRegExp (RegAlts tt) = tt
|
||||||
|
wordsOfRegExp _ = []
|
||||||
|
|
||||||
|
forCFItem :: CFTok -> CFRule -> Bool
|
||||||
|
forCFItem a (_,(_, CFTerm r : _)) = satRegExp r a
|
||||||
|
forCFItem _ _ = False
|
||||||
|
|
||||||
|
isCircularCF :: CFRule -> Bool
|
||||||
|
isCircularCF (_,(c', CFNonterm c:[])) = compatCF c' c
|
||||||
|
isCircularCF _ = False
|
||||||
|
--- we should make a test of circular chains, too
|
||||||
|
|
||||||
|
-- coercion to the older predef cf type
|
||||||
|
|
||||||
|
predefRules :: CFPredef -> CFTok -> [CFRule]
|
||||||
|
predefRules pre s = [atomCFRule c f s | (c,f) <- pre s]
|
||||||
|
|
||||||
151
src/GF/CF/CFIdent.hs
Normal file
151
src/GF/CF/CFIdent.hs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
module CFIdent where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import GFC
|
||||||
|
import Ident
|
||||||
|
import AbsGFC
|
||||||
|
import PrGrammar
|
||||||
|
import Str
|
||||||
|
import Char (toLower, toUpper)
|
||||||
|
|
||||||
|
-- symbols (categories, functions) for context-free grammars.
|
||||||
|
|
||||||
|
-- these types should be abstract
|
||||||
|
|
||||||
|
data CFTok =
|
||||||
|
TS String -- normal strings
|
||||||
|
| TC String -- strings that are ambiguous between upper or lower case
|
||||||
|
| TL String -- string literals
|
||||||
|
| TI Int -- integer literals
|
||||||
|
| TV Ident -- variables
|
||||||
|
| TM Int String -- metavariables; the integer identifies it
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
newtype CFCat = CFCat (CIdent,Label) deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
tS, tC, tL, tI, tV, tM :: String -> CFTok
|
||||||
|
tS = TS
|
||||||
|
tC = TC
|
||||||
|
tL = TL
|
||||||
|
tI = TI . read
|
||||||
|
tV = TV . identC
|
||||||
|
tM = TM 0
|
||||||
|
|
||||||
|
tInt :: Int -> CFTok
|
||||||
|
tInt = TI
|
||||||
|
|
||||||
|
prCFTok :: CFTok -> String
|
||||||
|
prCFTok t = case t of
|
||||||
|
TS s -> s
|
||||||
|
TC s -> s
|
||||||
|
TL s -> s
|
||||||
|
TI i -> show i
|
||||||
|
TV x -> prt x
|
||||||
|
TM i _ -> "?" ---
|
||||||
|
|
||||||
|
-- to build trees: the Atom contains a GF function, Cn | Meta | Vr | Literal
|
||||||
|
newtype CFFun = CFFun (Atom, Profile) deriving (Eq,Show)
|
||||||
|
|
||||||
|
type Profile = [([[Int]],[Int])]
|
||||||
|
|
||||||
|
|
||||||
|
-- the following functions should be used instead of constructors
|
||||||
|
|
||||||
|
-- to construct CF functions
|
||||||
|
|
||||||
|
mkCFFun :: Atom -> CFFun
|
||||||
|
mkCFFun t = CFFun (t,[])
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
getCFLiteral :: String -> Maybe (CFCat, CFFun)
|
||||||
|
getCFLiteral s = case lookupLiteral' s of
|
||||||
|
Ok (c, lit) -> Just (cat2CFCat c, mkCFFun lit)
|
||||||
|
_ -> Nothing
|
||||||
|
-}
|
||||||
|
|
||||||
|
varCFFun :: Ident -> CFFun
|
||||||
|
varCFFun = mkCFFun . AV
|
||||||
|
|
||||||
|
consCFFun :: CIdent -> CFFun
|
||||||
|
consCFFun = mkCFFun . AC
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
string2CFFun :: String -> CFFun
|
||||||
|
string2CFFun = consCFFun . Ident
|
||||||
|
-}
|
||||||
|
|
||||||
|
cfFun2String :: CFFun -> String
|
||||||
|
cfFun2String (CFFun (f,_)) = prt f
|
||||||
|
|
||||||
|
cfFun2Profile :: CFFun -> Profile
|
||||||
|
cfFun2Profile (CFFun (_,p)) = p
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
strPro2cfFun :: String -> Profile -> CFFun
|
||||||
|
strPro2cfFun str p = (CFFun (AC (Ident str), p))
|
||||||
|
-}
|
||||||
|
|
||||||
|
metaCFFun :: CFFun
|
||||||
|
metaCFFun = mkCFFun $ AM 0
|
||||||
|
|
||||||
|
-- to construct CF categories
|
||||||
|
|
||||||
|
-- belongs elsewhere
|
||||||
|
mkCIdent :: String -> String -> CIdent
|
||||||
|
mkCIdent m c = CIQ (identC m) (identC c)
|
||||||
|
|
||||||
|
ident2CFCat :: CIdent -> Ident -> CFCat
|
||||||
|
ident2CFCat mc d = CFCat (mc, L d)
|
||||||
|
|
||||||
|
-- standard way of making cf cat: label s
|
||||||
|
string2CFCat :: String -> String -> CFCat
|
||||||
|
string2CFCat m c = ident2CFCat (mkCIdent m c) (identC "s")
|
||||||
|
|
||||||
|
idents2CFCat :: Ident -> Ident -> CFCat
|
||||||
|
idents2CFCat m c = ident2CFCat (CIQ m c) (identC "s")
|
||||||
|
|
||||||
|
catVarCF :: CFCat
|
||||||
|
catVarCF = ident2CFCat (mkCIdent "_" "#Var") (identC "_") ----
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
uCFCat :: CFCat
|
||||||
|
uCFCat = cat2CFCat uCat
|
||||||
|
-}
|
||||||
|
|
||||||
|
moduleOfCFCat :: CFCat -> Ident
|
||||||
|
moduleOfCFCat (CFCat (CIQ m _, _)) = m
|
||||||
|
|
||||||
|
-- the opposite direction
|
||||||
|
cfCat2Cat :: CFCat -> CIdent
|
||||||
|
cfCat2Cat (CFCat (s,_)) = s
|
||||||
|
|
||||||
|
|
||||||
|
-- to construct CF tokens
|
||||||
|
|
||||||
|
string2CFTok :: String -> CFTok
|
||||||
|
string2CFTok = tS
|
||||||
|
|
||||||
|
str2cftoks :: Str -> [CFTok]
|
||||||
|
str2cftoks = map tS . words . sstr
|
||||||
|
|
||||||
|
-- decide if two token lists look the same (in parser postprocessing)
|
||||||
|
|
||||||
|
compatToks :: [CFTok] -> [CFTok] -> Bool
|
||||||
|
compatToks ts us = and [compatTok t u | (t,u) <- zip ts us]
|
||||||
|
|
||||||
|
compatTok t u = any (`elem` (alts t)) (alts u) where
|
||||||
|
alts u = case u of
|
||||||
|
TC (c:s) -> [toLower c : s, toUpper c : s]
|
||||||
|
_ -> [prCFTok u]
|
||||||
|
|
||||||
|
-- decide if two CFFuns have the same function head (profiles may differ)
|
||||||
|
|
||||||
|
compatCFFun :: CFFun -> CFFun -> Bool
|
||||||
|
compatCFFun (CFFun (f,_)) (CFFun (g,_)) = f == g
|
||||||
|
|
||||||
|
-- decide whether two categories match
|
||||||
|
-- the modifiers can be from different modules, but on the same extension
|
||||||
|
-- path, so there is no clash, and they can be safely ignored ---
|
||||||
|
compatCF :: CFCat -> CFCat -> Bool
|
||||||
|
----compatCF = (==)
|
||||||
|
compatCF (CFCat (CIQ _ c, l)) (CFCat (CIQ _ c', l')) = c==c' && l==l'
|
||||||
157
src/GF/CF/CanonToCF.hs
Normal file
157
src/GF/CF/CanonToCF.hs
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
module CanonToCF where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Option
|
||||||
|
import Ident
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
import PrGrammar
|
||||||
|
import CMacros
|
||||||
|
import qualified Modules as M
|
||||||
|
import CF
|
||||||
|
import CFIdent
|
||||||
|
import List (nub)
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- AR 27/1/2000 -- 3/12/2001 -- 8/6/2003
|
||||||
|
|
||||||
|
-- The main function: for a given cnc module m, build the CF grammar with all the
|
||||||
|
-- rules coming from modules that m extends. The categories are qualified by
|
||||||
|
-- the abstract module name a that m is of.
|
||||||
|
|
||||||
|
canon2cf :: Options -> CanonGrammar -> Ident -> Err CF
|
||||||
|
canon2cf opts gr c = do
|
||||||
|
let ms = M.allExtends gr c
|
||||||
|
a <- M.abstractOfConcrete gr c
|
||||||
|
let cncs = [m | (n, M.ModMod m) <- M.modules gr, elem n ms]
|
||||||
|
let mms = [(a, tree2list (M.jments m)) | m <- cncs]
|
||||||
|
rules0 <- liftM concat $ mapM (uncurry (cnc2cfCond opts)) mms
|
||||||
|
let rules = filter (not . isCircularCF) rules0 ---- temporarily here
|
||||||
|
let predef = const [] ---- mkCFPredef cfcats
|
||||||
|
return $ CF (groupCFRules rules, predef)
|
||||||
|
|
||||||
|
cnc2cfCond :: Options -> Ident -> [(Ident,Info)] -> Err [CFRule]
|
||||||
|
cnc2cfCond opts m gr =
|
||||||
|
liftM concat $
|
||||||
|
mapM lin2cf [(m,fun,cat,args,lin) | (fun, CncFun cat args lin _) <- gr]
|
||||||
|
|
||||||
|
type IFun = Ident
|
||||||
|
type ICat = CIdent
|
||||||
|
|
||||||
|
-- all CF rules corresponding to a linearization rule
|
||||||
|
lin2cf :: (Ident, IFun, ICat, [ArgVar], Term) -> Err [CFRule]
|
||||||
|
lin2cf (m,fun,cat,args,lin) = errIn ("building CF rule for" +++ prt fun) $ do
|
||||||
|
rhss0 <- allLinValues lin -- :: [(Label, [([Patt],Term)])]
|
||||||
|
rhss1 <- mapM (mkCFItems m) (concat rhss0) -- :: [(Label, [[PreCFItem]])]
|
||||||
|
mapM (mkCfRules m fun cat args) rhss1 >>= return . nub . concat
|
||||||
|
|
||||||
|
-- making sequences of CF items from every branch in a linearization
|
||||||
|
mkCFItems :: Ident -> (Label, [([Patt],Term)]) -> Err (Label, [[PreCFItem]])
|
||||||
|
mkCFItems m (lab,pts) = do
|
||||||
|
itemss <- mapM (term2CFItems m) (map snd pts)
|
||||||
|
return (lab, concat itemss) ---- combinations? (test!)
|
||||||
|
|
||||||
|
-- making CF rules from sequences of CF items
|
||||||
|
mkCfRules :: Ident -> IFun -> ICat -> [ArgVar] -> (Label, [[PreCFItem]]) -> Err [CFRule]
|
||||||
|
mkCfRules m fun cat args (lab, itss) = mapM mkOneRule itss
|
||||||
|
where
|
||||||
|
mkOneRule its = do
|
||||||
|
let nonterms = zip [0..] [(pos,d,v) | PNonterm _ pos d v <- its]
|
||||||
|
profile = mkProfile nonterms
|
||||||
|
cfcat = CFCat (redirectIdent m cat,lab)
|
||||||
|
cffun = CFFun (AC (CIQ m fun), profile)
|
||||||
|
cfits = map precf2cf its
|
||||||
|
return (cffun,(cfcat,cfits))
|
||||||
|
mkProfile nonterms = map mkOne args
|
||||||
|
where
|
||||||
|
mkOne (A c i) = mkOne (AB c 0 i)
|
||||||
|
mkOne (AB _ b i) = (map mkB [0..b-1], [k | (k,(j,_,True)) <- nonterms, j==i])
|
||||||
|
where
|
||||||
|
mkB j = [p | (p,(k, LV l,False)) <- nonterms, k == i, l == j]
|
||||||
|
|
||||||
|
-- intermediate data structure of CFItems with information for profiles
|
||||||
|
data PreCFItem =
|
||||||
|
PTerm RegExp -- like ordinary Terminal
|
||||||
|
| PNonterm CIdent Integer Label Bool -- cat, position, part/bind, whether arg
|
||||||
|
deriving Eq
|
||||||
|
|
||||||
|
precf2cf :: PreCFItem -> CFItem
|
||||||
|
precf2cf (PTerm r) = CFTerm r
|
||||||
|
precf2cf (PNonterm cm _ (L c) True) = CFNonterm (ident2CFCat cm c)
|
||||||
|
precf2cf (PNonterm _ _ _ False) = CFNonterm catVarCF
|
||||||
|
|
||||||
|
|
||||||
|
-- the main job in translating linearization rules into sequences of cf items
|
||||||
|
term2CFItems :: Ident -> Term -> Err [[PreCFItem]]
|
||||||
|
term2CFItems m t = errIn "forming cf items" $ case t of
|
||||||
|
S c _ -> t2c c
|
||||||
|
|
||||||
|
T _ cc -> do
|
||||||
|
its <- mapM t2c [t | Cas _ t <- cc]
|
||||||
|
tryMkCFTerm (concat its)
|
||||||
|
|
||||||
|
C t1 t2 -> do
|
||||||
|
its1 <- t2c t1
|
||||||
|
its2 <- t2c t2
|
||||||
|
return [x ++ y | x <- its1, y <- its2]
|
||||||
|
|
||||||
|
FV ts -> do
|
||||||
|
its <- mapM t2c ts
|
||||||
|
tryMkCFTerm (concat its)
|
||||||
|
|
||||||
|
P arg s -> extrR arg s
|
||||||
|
|
||||||
|
K (KS s) -> return [[PTerm (RegAlts [s]) | not (null s)]]
|
||||||
|
|
||||||
|
E -> return [[]]
|
||||||
|
|
||||||
|
K (KP d vs) -> do
|
||||||
|
let its = [PTerm (RegAlts [s]) | s <- d]
|
||||||
|
let itss = [[PTerm (RegAlts [s]) | s <- t] | Var t _ <- vs]
|
||||||
|
tryMkCFTerm (its : itss)
|
||||||
|
|
||||||
|
_ -> prtBad "no cf for" t ----
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
t2c = term2CFItems m
|
||||||
|
|
||||||
|
-- optimize the number of rules by a factorization
|
||||||
|
tryMkCFTerm :: [[PreCFItem]] -> Err [[PreCFItem]]
|
||||||
|
tryMkCFTerm ii@(its:itss) | all (\x -> length x == length its) itss =
|
||||||
|
case mapM mkOne (counterparts ii) of
|
||||||
|
Ok tt -> return [tt]
|
||||||
|
_ -> return ii
|
||||||
|
where
|
||||||
|
mkOne cfits = case mapM mkOneTerm cfits of
|
||||||
|
Ok tt -> return $ PTerm (RegAlts (concat (nub tt)))
|
||||||
|
_ -> mkOneNonTerm cfits
|
||||||
|
mkOneTerm (PTerm (RegAlts t)) = return t
|
||||||
|
mkOneTerm _ = Bad ""
|
||||||
|
mkOneNonTerm (n@(PNonterm _ _ _ _) : cc) =
|
||||||
|
if all (== n) cc
|
||||||
|
then return n
|
||||||
|
else Bad ""
|
||||||
|
mkOneNonTerm _ = Bad ""
|
||||||
|
counterparts ll = [map (!! i) ll | i <- [0..length (head ll) - 1]]
|
||||||
|
tryMkCFTerm itss = return itss
|
||||||
|
|
||||||
|
extrR arg lab = case (arg,lab) of
|
||||||
|
(Arg (A cat pos), l@(L _)) -> return [[PNonterm (CIQ m cat) pos l True]]
|
||||||
|
(Arg (A cat pos), l@(LV _)) -> return [[PNonterm (CIQ m cat) pos l False]]
|
||||||
|
(Arg (AB cat pos b), l@(L _)) -> return [[PNonterm (CIQ m cat) pos l True]]
|
||||||
|
(Arg (AB cat pos b), l@(LV _)) -> return [[PNonterm (CIQ m cat) pos l False]]
|
||||||
|
---- ??
|
||||||
|
_ -> prtBad "cannot extract record field from" arg
|
||||||
|
|
||||||
|
{- Proof + 1 @ 4 catVarCF :: CFCat
|
||||||
|
PNonterm CIdent Integer Label Bool -- cat, position, part/bind, whether arg
|
||||||
|
|
||||||
|
|
||||||
|
mkCFPredef :: [CFCat] -> CFPredef
|
||||||
|
mkCFPredef cats s =
|
||||||
|
[(cat, metaCFFun) | TM _ _ <- [s], cat <- cats] ++
|
||||||
|
[(cat, varCFFun x) | TV x <- [s], cat <- cats] ++
|
||||||
|
[(cat, lit) | TL t <- [s], Just (cat,lit) <- [getCFLiteral t]] ++
|
||||||
|
[(cat, lit) | TI i <- [s], Just (cat,lit) <- [getCFLiteral (show i)]] ---
|
||||||
|
-}
|
||||||
166
src/GF/CF/ChartParser.hs
Normal file
166
src/GF/CF/ChartParser.hs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
|
||||||
|
module ChartParser (chartParser) where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import CF
|
||||||
|
import CFIdent
|
||||||
|
import PPrCF (prCFItem)
|
||||||
|
|
||||||
|
import OrdSet
|
||||||
|
import OrdMap2
|
||||||
|
|
||||||
|
import List (groupBy)
|
||||||
|
|
||||||
|
type Token = CFTok
|
||||||
|
type Name = CFFun
|
||||||
|
type Category = CFItem
|
||||||
|
type Grammar = ([Production], Terminal)
|
||||||
|
type Production = (Name, Category, [Category])
|
||||||
|
type Terminal = Token -> [(Category, Maybe Name)]
|
||||||
|
type GParser = Grammar -> Category -> [Token] -> ([ParseTree],String)
|
||||||
|
data ParseTree = Node Name Category [ParseTree] | Leaf Token
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- converting between GF parsing and CFG parsing
|
||||||
|
|
||||||
|
buildParser :: GParser -> CF -> CFCat -> CFParser
|
||||||
|
buildParser gparser cf = parse
|
||||||
|
where
|
||||||
|
parse = \start input ->
|
||||||
|
let parse2 = parse' (CFNonterm start) input in
|
||||||
|
([(parse2tree t, []) | t <- fst parse2], snd parse2)
|
||||||
|
parse' = gparser (cf2grammar cf)
|
||||||
|
|
||||||
|
cf2grammar :: CF -> Grammar
|
||||||
|
cf2grammar cf = (productions, terminal)
|
||||||
|
where
|
||||||
|
productions = [ (name, CFNonterm cat, rhs) |
|
||||||
|
(name, (cat, rhs)) <- cfRules ]
|
||||||
|
terminal tok = [ (CFNonterm cat, Just name) |
|
||||||
|
(cat, name) <- cfPredef tok ]
|
||||||
|
++
|
||||||
|
[ (item, Nothing) |
|
||||||
|
item <- elems rhsItems,
|
||||||
|
matchCFTerm item tok ]
|
||||||
|
cfRules = rulesOfCF cf
|
||||||
|
cfPredef = predefOfCF cf
|
||||||
|
rhsItems :: Set Category
|
||||||
|
rhsItems = union [ makeSet rhs | (_, (_, rhs)) <- cfRules ]
|
||||||
|
|
||||||
|
parse2tree :: ParseTree -> CFTree
|
||||||
|
parse2tree (Node name (CFNonterm cat) trees) = CFTree (name, (cat, trees'))
|
||||||
|
where
|
||||||
|
trees' = [ parse2tree t | t@(Node _ _ _) <- trees ] -- ignore leafs
|
||||||
|
|
||||||
|
maybeNode :: Maybe Name -> Category -> Token -> ParseTree
|
||||||
|
maybeNode (Just name) cat tok = Node name cat [Leaf tok]
|
||||||
|
maybeNode Nothing _ tok = Leaf tok
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- chart parsing (bottom up kilbury-like)
|
||||||
|
|
||||||
|
type Chart = [CState]
|
||||||
|
type CState = Set Edge
|
||||||
|
type Edge = (Int, Category, [Category])
|
||||||
|
type Passive = (Int, Int, Category)
|
||||||
|
|
||||||
|
chartParser :: CF -> CFCat -> CFParser
|
||||||
|
chartParser = buildParser chartParser0
|
||||||
|
|
||||||
|
chartParser0 :: GParser
|
||||||
|
chartParser0 (productions, terminal) = cparse
|
||||||
|
where
|
||||||
|
emptyCats :: Set Category
|
||||||
|
emptyCats = empties emptySet
|
||||||
|
where
|
||||||
|
empties cats | cats==cats' = cats
|
||||||
|
| otherwise = empties cats'
|
||||||
|
where cats' = makeSet [ cat | (_, cat, rhs) <- productions,
|
||||||
|
all (`elemSet` cats) rhs ]
|
||||||
|
|
||||||
|
grammarMap :: Map Category [(Name, [Category])]
|
||||||
|
grammarMap = makeMapWith (++)
|
||||||
|
[ (cat, [(name,rhs)]) | (name, cat, rhs) <- productions ]
|
||||||
|
|
||||||
|
leftCornerMap :: Map Category (Set (Category,[Category]))
|
||||||
|
leftCornerMap = makeMapWith (<++>) [ (a, unitSet (b, bs)) |
|
||||||
|
(_, b, abs) <- productions,
|
||||||
|
(a : bs) <- removeNullable abs ]
|
||||||
|
|
||||||
|
removeNullable :: [Category] -> [[Category]]
|
||||||
|
removeNullable [] = []
|
||||||
|
removeNullable cats@(cat:cats')
|
||||||
|
| cat `elemSet` emptyCats = cats : removeNullable cats'
|
||||||
|
| otherwise = [cats]
|
||||||
|
|
||||||
|
cparse :: Category -> [Token] -> ([ParseTree], String)
|
||||||
|
cparse start input = case lookup (0, length input, start) edgeTrees of
|
||||||
|
Just trees -> (trees, "Chart:" ++++ prChart passiveEdges)
|
||||||
|
Nothing -> ([], "Chart:" ++++ prChart passiveEdges)
|
||||||
|
where
|
||||||
|
finalChart :: Chart
|
||||||
|
finalChart = map buildState initialChart
|
||||||
|
|
||||||
|
finalChartMap :: [Map Category (Set Edge)]
|
||||||
|
finalChartMap = map stateMap finalChart
|
||||||
|
|
||||||
|
stateMap :: CState -> Map Category (Set Edge)
|
||||||
|
stateMap state = makeMapWith (<++>) [ (a, unitSet (i,b,bs)) |
|
||||||
|
(i, b, a:bs) <- elems state ]
|
||||||
|
|
||||||
|
initialChart :: Chart
|
||||||
|
initialChart = emptySet : map initialState (zip [0..] input)
|
||||||
|
where initialState (j, sym) = makeSet [ (j, cat, []) |
|
||||||
|
(cat, _) <- terminal sym ]
|
||||||
|
|
||||||
|
buildState :: CState -> CState
|
||||||
|
buildState = limit more
|
||||||
|
where more (j, a, []) = ordSet [ (j, b, bs) |
|
||||||
|
(b, bs) <- elems (lookupWith emptySet leftCornerMap a) ]
|
||||||
|
<++>
|
||||||
|
lookupWith emptySet (finalChartMap !! j) a
|
||||||
|
more (j, b, a:bs) = ordSet [ (j, b, bs) |
|
||||||
|
a `elemSet` emptyCats ]
|
||||||
|
|
||||||
|
passiveEdges :: [Passive]
|
||||||
|
passiveEdges = [ (i, j, cat) |
|
||||||
|
(j, state) <- zip [0..] finalChart,
|
||||||
|
(i, cat, []) <- elems state ]
|
||||||
|
++
|
||||||
|
[ (i, i, cat) |
|
||||||
|
i <- [0 .. length input],
|
||||||
|
cat <- elems emptyCats ]
|
||||||
|
|
||||||
|
edgeTrees :: [ (Passive, [ParseTree]) ]
|
||||||
|
edgeTrees = [ (edge, treesFor edge) | edge <- passiveEdges ]
|
||||||
|
|
||||||
|
edgeTreesMap :: Map (Int, Category) [(Int, [ParseTree])]
|
||||||
|
edgeTreesMap = makeMapWith (++) [ ((i,c), [(j,trees)]) |
|
||||||
|
((i,j,c), trees) <- edgeTrees ]
|
||||||
|
|
||||||
|
treesFor :: Passive -> [ParseTree]
|
||||||
|
treesFor (i, j, cat) = [ Node name cat trees |
|
||||||
|
(name, rhs) <- lookupWith [] grammarMap cat,
|
||||||
|
trees <- children rhs i j ]
|
||||||
|
++
|
||||||
|
[ maybeNode name cat tok |
|
||||||
|
i == j-1,
|
||||||
|
let tok = input !! i,
|
||||||
|
Just name <- [lookup cat (terminal tok)] ]
|
||||||
|
|
||||||
|
children :: [Category] -> Int -> Int -> [[ParseTree]]
|
||||||
|
children [] i k = [ [] | i == k ]
|
||||||
|
children (c:cs) i k = [ tree : rest |
|
||||||
|
i <= k,
|
||||||
|
(j, trees) <- lookupWith [] edgeTreesMap (i,c),
|
||||||
|
rest <- children cs j k,
|
||||||
|
tree <- trees ]
|
||||||
|
|
||||||
|
|
||||||
|
-- AR 10/12/2002
|
||||||
|
|
||||||
|
prChart :: [Passive] -> String
|
||||||
|
prChart = unlines . map (unwords . map prOne) . positions where
|
||||||
|
prOne (i,j,it) = show i ++ "-" ++ show j ++ "-" ++ prCFItem it
|
||||||
|
positions = groupBy (\ (i,_,_) (j,_,_) -> i == j)
|
||||||
59
src/GF/CF/PPrCF.hs
Normal file
59
src/GF/CF/PPrCF.hs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
module PPrCF where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import CF
|
||||||
|
import CFIdent
|
||||||
|
import AbsGFC
|
||||||
|
import PrGrammar
|
||||||
|
|
||||||
|
-- printing and parsing CF grammars, rules, and trees AR 26/1/2000 -- 9/6/2003
|
||||||
|
---- use the Print class instead!
|
||||||
|
|
||||||
|
prCF :: CF -> String
|
||||||
|
prCF = unlines . (map prCFRule) . rulesOfCF -- hiding the literal recogn function
|
||||||
|
|
||||||
|
prCFTree :: CFTree -> String
|
||||||
|
prCFTree (CFTree (fun, (_,trees))) = prCFFun fun ++ prs trees where
|
||||||
|
prs [] = ""
|
||||||
|
prs ts = " " ++ unwords (map ps ts)
|
||||||
|
ps t@(CFTree (_,(_,[]))) = prCFTree t
|
||||||
|
ps t = prParenth (prCFTree t)
|
||||||
|
|
||||||
|
prCFRule :: CFRule -> String
|
||||||
|
prCFRule (fun,(cat,its)) =
|
||||||
|
prCFFun fun ++ "." +++ prCFCat cat +++ "::=" +++
|
||||||
|
unwords (map prCFItem its) +++ ";"
|
||||||
|
|
||||||
|
prCFFun :: CFFun -> String
|
||||||
|
prCFFun = prCFFun' True ---- False -- print profiles for debug
|
||||||
|
|
||||||
|
prCFFun' :: Bool -> CFFun -> String
|
||||||
|
prCFFun' profs (CFFun (t, p)) = prt t ++ pp p where
|
||||||
|
pp p = if (not profs || normal p) then "" else "_" ++ concat (map show p)
|
||||||
|
normal p = and [x==y && null b | ((b,x),y) <- zip p (map (:[]) [0..])]
|
||||||
|
|
||||||
|
prCFCat :: CFCat -> String
|
||||||
|
prCFCat (CFCat (c,l)) = prt c ++ "-" ++ prt l ----
|
||||||
|
|
||||||
|
prCFItem (CFNonterm c) = prCFCat c
|
||||||
|
prCFItem (CFTerm a) = prRegExp a
|
||||||
|
|
||||||
|
prRegExp (RegAlts tt) = case tt of
|
||||||
|
[t] -> prQuotedString t
|
||||||
|
_ -> prParenth (prTList " | " (map prQuotedString tt))
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
-- rules have an amazingly easy parser, if we use the format
|
||||||
|
-- fun. C -> item1 item2 ... where unquoted items are treated as cats
|
||||||
|
-- Actually would be nice to add profiles to this.
|
||||||
|
|
||||||
|
getCFRule :: String -> Maybe CFRule
|
||||||
|
getCFRule s = getcf (wrds s) where
|
||||||
|
getcf ww | length ww > 2 && ww !! 2 `elem` ["->", "::="] =
|
||||||
|
Just (string2CFFun (init fun), (string2CFCat cat, map mkIt its)) where
|
||||||
|
fun : cat : _ : its = words s
|
||||||
|
mkIt ('"':w@(_:_)) = atomCFTerm (string2CFTok (init w))
|
||||||
|
mkIt w = CFNonterm (string2CFCat w)
|
||||||
|
getcf _ = Nothing
|
||||||
|
wrds = takeWhile (/= ";") . words -- to permit semicolon in the end
|
||||||
|
-}
|
||||||
95
src/GF/CF/Profile.hs
Normal file
95
src/GF/CF/Profile.hs
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
module Profile (postParse) where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
import qualified Ident as I
|
||||||
|
import CMacros
|
||||||
|
---import MMacros
|
||||||
|
import CF
|
||||||
|
import CFIdent
|
||||||
|
import PPrCF -- for error msg
|
||||||
|
import PrGrammar
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
import List (nub)
|
||||||
|
|
||||||
|
|
||||||
|
-- restoring parse trees for discontinuous constituents, bindings, etc. AR 25/1/2001
|
||||||
|
-- revised 8/4/2002 for the new profile structure
|
||||||
|
|
||||||
|
postParse :: CFTree -> Err Exp
|
||||||
|
postParse tree = do
|
||||||
|
iterm <- errIn "postprocessing initial parse tree" $ tree2term tree
|
||||||
|
return $ term2trm iterm
|
||||||
|
|
||||||
|
-- an intermediate data structure
|
||||||
|
data ITerm = ITerm (Atom, BindVs) [ITerm] | IMeta deriving (Eq,Show)
|
||||||
|
type BindVs = [[I.Ident]]
|
||||||
|
|
||||||
|
-- the job is done in two passes:
|
||||||
|
-- (1) tree2term: restore constituent order from Profile
|
||||||
|
-- (2) term2trm: restore Bindings from Binds
|
||||||
|
|
||||||
|
tree2term :: CFTree -> Err ITerm
|
||||||
|
tree2term (CFTree (cff@(CFFun (fun,pro)), (_,trees))) = case fun of
|
||||||
|
AM _ -> return IMeta
|
||||||
|
_ -> do
|
||||||
|
args <- mapM mkArg pro
|
||||||
|
binds <- mapM mkBinds pro
|
||||||
|
return $ ITerm (fun, binds) args
|
||||||
|
where
|
||||||
|
mkArg (_,arg) = case arg of
|
||||||
|
[x] -> do -- one occurrence
|
||||||
|
trx <- trees !? x
|
||||||
|
tree2term trx
|
||||||
|
[] -> return IMeta -- suppression
|
||||||
|
_ -> do -- reduplication
|
||||||
|
trees' <- mapM (trees !?) arg
|
||||||
|
xs1 <- mapM tree2term trees'
|
||||||
|
xs2 <- checkArity xs1
|
||||||
|
unif xs2
|
||||||
|
|
||||||
|
checkArity xs = if length (nub [length xx | ITerm _ xx <- xs']) > 1
|
||||||
|
then Bad "arity error"
|
||||||
|
else return xs'
|
||||||
|
where xs' = [t | t@(ITerm _ _) <- xs]
|
||||||
|
unif [] = return $ IMeta
|
||||||
|
unif xs@(ITerm fp@(f,_) xx : ts) = do
|
||||||
|
let hs = [h | ITerm (h,_) _ <- ts]
|
||||||
|
testErr (all (==f) hs) -- if fails, hs must be nonempty
|
||||||
|
("unification expects" +++ prt f +++ "but found" +++ prt (head hs))
|
||||||
|
xx' <- mapM unifArg [0 .. length xx - 1]
|
||||||
|
return $ ITerm fp xx'
|
||||||
|
where
|
||||||
|
unifArg i = tryUnif [zz !! i | ITerm _ zz <- xs]
|
||||||
|
tryUnif xx = case [t | t@(ITerm _ _) <- xx] of
|
||||||
|
[] -> return IMeta
|
||||||
|
x:xs -> if all (==x) xs
|
||||||
|
then return x
|
||||||
|
else Bad "failed to unify"
|
||||||
|
|
||||||
|
mkBinds (xss,_) = mapM mkBind xss
|
||||||
|
mkBind xs = do
|
||||||
|
ts <- mapM (trees !?) xs
|
||||||
|
let vs = [x | CFTree (CFFun (AV x,_),(_,[])) <- ts]
|
||||||
|
testErr (length ts == length vs) "non-variable in bound position"
|
||||||
|
case vs of
|
||||||
|
[x] -> return x
|
||||||
|
[] -> return $ I.identC "h_" ---- uBoundVar
|
||||||
|
y:ys -> do
|
||||||
|
testErr (all (==y) ys) ("fail to unify bindings of" +++ prt y)
|
||||||
|
return y
|
||||||
|
|
||||||
|
term2trm :: ITerm -> Exp
|
||||||
|
term2trm IMeta = EAtom (AM 0) ---- mExp0
|
||||||
|
term2trm (ITerm (fun, binds) terms) =
|
||||||
|
let bterms = zip binds terms
|
||||||
|
in mkAppAtom fun [mkAbsR xs (term2trm t) | (xs,t) <- bterms]
|
||||||
|
|
||||||
|
--- these are deprecated
|
||||||
|
where
|
||||||
|
mkAbsR c e = foldr EAbs e c
|
||||||
|
mkAppAtom a = mkApp (EAtom a)
|
||||||
|
mkApp = foldl EApp
|
||||||
160
src/GF/Canon/AbsGFC.hs
Normal file
160
src/GF/Canon/AbsGFC.hs
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
module AbsGFC where
|
||||||
|
|
||||||
|
import Ident --H
|
||||||
|
|
||||||
|
-- Haskell module generated by the BNF converter, except --H
|
||||||
|
|
||||||
|
-- newtype Ident = Ident String deriving (Eq,Ord,Show) --H
|
||||||
|
data Canon =
|
||||||
|
Gr [Module]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Module =
|
||||||
|
Mod ModType Extend Open [Flag] [Def]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data ModType =
|
||||||
|
MTAbs Ident
|
||||||
|
| MTCnc Ident Ident
|
||||||
|
| MTRes Ident
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Extend =
|
||||||
|
Ext Ident
|
||||||
|
| NoExt
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Open =
|
||||||
|
NoOpens
|
||||||
|
| Opens [Ident]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Flag =
|
||||||
|
Flg Ident Ident
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Def =
|
||||||
|
AbsDCat Ident [Decl] [CIdent]
|
||||||
|
| AbsDFun Ident Exp Exp
|
||||||
|
| ResDPar Ident [ParDef]
|
||||||
|
| ResDOper Ident CType Term
|
||||||
|
| CncDCat Ident CType Term Term
|
||||||
|
| CncDFun Ident CIdent [ArgVar] Term Term
|
||||||
|
| AnyDInd Ident Status Ident
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data ParDef =
|
||||||
|
ParD Ident [CType]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Status =
|
||||||
|
Canon
|
||||||
|
| NonCan
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data CIdent =
|
||||||
|
CIQ Ident Ident
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Exp =
|
||||||
|
EApp Exp Exp
|
||||||
|
| EProd Ident Exp Exp
|
||||||
|
| EAbs Ident Exp
|
||||||
|
| EAtom Atom
|
||||||
|
| EEq [Equation]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Sort =
|
||||||
|
SType
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Equation =
|
||||||
|
Equ [APatt] Exp
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data APatt =
|
||||||
|
APC CIdent [APatt]
|
||||||
|
| APV Ident
|
||||||
|
| APS String
|
||||||
|
| API Integer
|
||||||
|
| APW
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Atom =
|
||||||
|
AC CIdent
|
||||||
|
| AD CIdent
|
||||||
|
| AV Ident
|
||||||
|
| AM Integer
|
||||||
|
| AS String
|
||||||
|
| AI Integer
|
||||||
|
| AT Sort
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Decl =
|
||||||
|
Decl Ident Exp
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data CType =
|
||||||
|
RecType [Labelling]
|
||||||
|
| Table CType CType
|
||||||
|
| Cn CIdent
|
||||||
|
| TStr
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Labelling =
|
||||||
|
Lbg Label CType
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Term =
|
||||||
|
Arg ArgVar
|
||||||
|
| I CIdent
|
||||||
|
| Con CIdent [Term]
|
||||||
|
| LI Ident
|
||||||
|
| R [Assign]
|
||||||
|
| P Term Label
|
||||||
|
| T CType [Case]
|
||||||
|
| S Term Term
|
||||||
|
| C Term Term
|
||||||
|
| FV [Term]
|
||||||
|
| K Tokn
|
||||||
|
| E
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Tokn =
|
||||||
|
KS String
|
||||||
|
| KP [String] [Variant]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Assign =
|
||||||
|
Ass Label Term
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Case =
|
||||||
|
Cas [Patt] Term
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Variant =
|
||||||
|
Var [String] [String]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Label =
|
||||||
|
L Ident
|
||||||
|
| LV Integer
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data ArgVar =
|
||||||
|
A Ident Integer
|
||||||
|
| AB Ident Integer Integer
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data Patt =
|
||||||
|
PC CIdent [Patt]
|
||||||
|
| PV Ident
|
||||||
|
| PW
|
||||||
|
| PR [PattAssign]
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
|
data PattAssign =
|
||||||
|
PAss Label Patt
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
|
||||||
234
src/GF/Canon/CMacros.hs
Normal file
234
src/GF/Canon/CMacros.hs
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
module CMacros where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
import qualified Ident as A ---- no need to qualif? 21/9
|
||||||
|
import PrGrammar
|
||||||
|
import Str
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Char
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- macros for concrete syntax in GFC that do not need lookup in a grammar
|
||||||
|
|
||||||
|
markFocus :: Term -> Term
|
||||||
|
markFocus = markSubterm "[*" "*]"
|
||||||
|
|
||||||
|
markSubterm :: String -> String -> Term -> Term
|
||||||
|
markSubterm beg end t = case t of
|
||||||
|
R rs -> R $ map markField rs
|
||||||
|
T ty cs -> T ty [Cas p (mark v) | Cas p v <- cs]
|
||||||
|
_ -> foldr1 C [tK beg, t, tK end] -- t : Str guaranteed?
|
||||||
|
where
|
||||||
|
mark = markSubterm beg end
|
||||||
|
markField lt@(Ass l t) = if isLinLabel l then (Ass l (mark t)) else lt
|
||||||
|
isLinLabel (L (A.IC s)) = case s of ----
|
||||||
|
's':cs -> all isDigit cs
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
tK :: String -> Term
|
||||||
|
tK = K . KS
|
||||||
|
|
||||||
|
term2patt :: Term -> Err Patt
|
||||||
|
term2patt trm = case trm of
|
||||||
|
Con c aa -> do
|
||||||
|
aa' <- mapM term2patt aa
|
||||||
|
return (PC c aa')
|
||||||
|
R r -> do
|
||||||
|
let (ll,aa) = unzip [(l,a) | Ass l a <- r]
|
||||||
|
aa' <- mapM term2patt aa
|
||||||
|
return (PR (map (uncurry PAss) (zip ll aa')))
|
||||||
|
LI x -> return $ PV x
|
||||||
|
_ -> prtBad "no pattern corresponds to term" trm
|
||||||
|
|
||||||
|
patt2term :: Patt -> Term
|
||||||
|
patt2term p = case p of
|
||||||
|
PC x ps -> Con x (map patt2term ps)
|
||||||
|
PV x -> LI x
|
||||||
|
PW -> anyTerm ----
|
||||||
|
PR pas -> R [ Ass lbl (patt2term q) | PAss lbl q <- pas ]
|
||||||
|
|
||||||
|
anyTerm :: Term
|
||||||
|
anyTerm = LI (A.identC "_") --- should not happen
|
||||||
|
|
||||||
|
matchPatt cs0 trm = term2patt trm >>= match cs0 where
|
||||||
|
match cs t =
|
||||||
|
case cs of
|
||||||
|
Cas ps b :_ | elem t ps -> return b
|
||||||
|
_:cs' -> match cs' t
|
||||||
|
[] -> Bad $ "pattern not found for" +++ prt t
|
||||||
|
+++ "among" ++++ unlines (map prt cs0) ---- debug
|
||||||
|
|
||||||
|
defLinType :: CType
|
||||||
|
defLinType = RecType [Lbg (L (A.identC "s")) TStr]
|
||||||
|
|
||||||
|
defLindef :: Term
|
||||||
|
defLindef = R [Ass (L (A.identC "s")) (Arg (A (A.identC "str") 0))]
|
||||||
|
|
||||||
|
strsFromTerm :: Term -> Err [Str]
|
||||||
|
strsFromTerm t = case t of
|
||||||
|
K (KS s) -> return [str s]
|
||||||
|
K (KP d vs) -> return $ [Str [TN d [(s,v) | Var s v <- vs]]]
|
||||||
|
C s t -> do
|
||||||
|
s' <- strsFromTerm s
|
||||||
|
t' <- strsFromTerm t
|
||||||
|
return [plusStr x y | x <- s', y <- t']
|
||||||
|
FV ts -> liftM concat $ mapM strsFromTerm ts
|
||||||
|
E -> return [str []]
|
||||||
|
_ -> return [str ("BUG[" ++ prt t ++ "]")] ---- debug
|
||||||
|
---- _ -> prtBad "cannot get Str from term " t
|
||||||
|
|
||||||
|
-- recursively collect all branches in a table
|
||||||
|
allInTable :: Term -> [Term]
|
||||||
|
allInTable t = case t of
|
||||||
|
T _ ts -> concatMap (\ (Cas _ v) -> allInTable v) ts --- expand ?
|
||||||
|
_ -> [t]
|
||||||
|
|
||||||
|
-- to gather s-fields; assumes term in normal form, preserves label
|
||||||
|
allLinFields :: Term -> Err [[(Label,Term)]]
|
||||||
|
allLinFields trm = case trm of
|
||||||
|
---- R rs -> return [[(l,t) | (l,(Just ty,t)) <- rs, isStrType ty]] -- good
|
||||||
|
R rs -> return [[(l,t) | Ass l t <- rs, isLinLabel l]] ---- bad
|
||||||
|
FV ts -> do
|
||||||
|
lts <- mapM allLinFields ts
|
||||||
|
return $ concat lts
|
||||||
|
_ -> prtBad "fields can only be sought in a record not in" trm
|
||||||
|
|
||||||
|
---- deprecated
|
||||||
|
isLinLabel l = case l of
|
||||||
|
L (A.IC ('s':cs)) | all isDigit cs -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
-- to gather ultimate cases in a table; preserves pattern list
|
||||||
|
allCaseValues :: Term -> [([Patt],Term)]
|
||||||
|
allCaseValues trm = case trm of
|
||||||
|
T _ cs -> [(p:ps, t) | Cas pp t0 <- cs, p <- pp, (ps,t) <- allCaseValues t0]
|
||||||
|
_ -> [([],trm)]
|
||||||
|
|
||||||
|
-- to gather all linearizations; assumes normal form, preserves label and args
|
||||||
|
allLinValues :: Term -> Err [[(Label,[([Patt],Term)])]]
|
||||||
|
allLinValues trm = do
|
||||||
|
lts <- allLinFields trm
|
||||||
|
mapM (mapPairsM (return . allCaseValues)) lts
|
||||||
|
|
||||||
|
redirectIdent n f@(CIQ _ c) = CIQ n c
|
||||||
|
|
||||||
|
|
||||||
|
{- ---- to be removed 21/9
|
||||||
|
-- to analyse types and terms into eta normal form
|
||||||
|
|
||||||
|
typeForm :: Exp -> Err (Context, Exp, [Exp])
|
||||||
|
typeForm e = do
|
||||||
|
(cont,val) <- getContext e
|
||||||
|
(cat,args) <- getArgs val
|
||||||
|
return (cont,cat,args)
|
||||||
|
|
||||||
|
getContext :: Exp -> Err (Context, Exp)
|
||||||
|
getContext e = case e of
|
||||||
|
EProd x a b -> do
|
||||||
|
(g,b') <- getContext b
|
||||||
|
return ((x,a):g,b')
|
||||||
|
_ -> return ([],e)
|
||||||
|
|
||||||
|
valAtom :: Exp -> Err Atom
|
||||||
|
valAtom e = do
|
||||||
|
(_,val,_) <- typeForm e
|
||||||
|
case val of
|
||||||
|
EAtom a -> return a
|
||||||
|
_ -> prtBad "atom expected instead of" val
|
||||||
|
|
||||||
|
valCat :: Exp -> Err CIdent
|
||||||
|
valCat e = do
|
||||||
|
a <- valAtom e
|
||||||
|
case a of
|
||||||
|
AC c -> return c
|
||||||
|
_ -> prtBad "cat expected instead of" a
|
||||||
|
|
||||||
|
termForm :: Exp -> Err ([A.Ident], Exp, [Exp])
|
||||||
|
termForm e = do
|
||||||
|
(cont,val) <- getBinds e
|
||||||
|
(cat,args) <- getArgs val
|
||||||
|
return (cont,cat,args)
|
||||||
|
|
||||||
|
getBinds :: Exp -> Err ([A.Ident], Exp)
|
||||||
|
getBinds e = case e of
|
||||||
|
EAbs x b -> do
|
||||||
|
(g,b') <- getBinds b
|
||||||
|
return (x:g,b')
|
||||||
|
_ -> return ([],e)
|
||||||
|
|
||||||
|
getArgs :: Exp -> Err (Exp,[Exp])
|
||||||
|
getArgs = get [] where
|
||||||
|
get xs e = case e of
|
||||||
|
EApp f a -> get (a:xs) f
|
||||||
|
_ -> return (e, reverse xs)
|
||||||
|
|
||||||
|
-- the inverses of these
|
||||||
|
|
||||||
|
mkProd :: Context -> Exp -> Exp
|
||||||
|
mkProd c e = foldr (uncurry EProd) e c
|
||||||
|
|
||||||
|
mkApp :: Exp -> [Exp] -> Exp
|
||||||
|
mkApp = foldl EApp
|
||||||
|
|
||||||
|
mkAppAtom :: Atom -> [Exp] -> Exp
|
||||||
|
mkAppAtom a = mkApp (EAtom a)
|
||||||
|
|
||||||
|
mkAppCons :: CIdent -> [Exp] -> Exp
|
||||||
|
mkAppCons c = mkAppAtom $ AC c
|
||||||
|
|
||||||
|
mkType :: Context -> Exp -> [Exp] -> Exp
|
||||||
|
mkType c e xs = mkProd c $ mkApp e xs
|
||||||
|
|
||||||
|
mkAbs :: Context -> Exp -> Exp
|
||||||
|
mkAbs c e = foldr EAbs e $ map fst c
|
||||||
|
|
||||||
|
mkTerm :: Context -> Exp -> [Exp] -> Exp
|
||||||
|
mkTerm c e xs = mkAbs c $ mkApp e xs
|
||||||
|
|
||||||
|
mkAbsR :: [A.Ident] -> Exp -> Exp
|
||||||
|
mkAbsR c e = foldr EAbs e c
|
||||||
|
|
||||||
|
mkTermR :: [A.Ident] -> Exp -> [Exp] -> Exp
|
||||||
|
mkTermR c e xs = mkAbsR c $ mkApp e xs
|
||||||
|
|
||||||
|
-- this is used to create heuristic menus
|
||||||
|
eqCatId :: Cat -> Atom -> Bool
|
||||||
|
eqCatId (CIQ _ c) b = case b of
|
||||||
|
AC (CIQ _ d) -> c == d
|
||||||
|
AD (CIQ _ d) -> c == d
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
-- a very weak notion of "compatible value category"
|
||||||
|
compatCat :: Cat -> Type -> Bool
|
||||||
|
compatCat c t = case t of
|
||||||
|
EAtom b -> eqCatId c b
|
||||||
|
EApp f _ -> compatCat c f
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
-- this is the way an atomic category looks as a type
|
||||||
|
|
||||||
|
cat2type :: Cat -> Type
|
||||||
|
cat2type = EAtom . AC
|
||||||
|
|
||||||
|
compatType :: Type -> Type -> Bool
|
||||||
|
compatType t = case t of
|
||||||
|
EAtom (AC c) -> compatCat c
|
||||||
|
_ -> (t ==)
|
||||||
|
|
||||||
|
type Fun = CIdent
|
||||||
|
type Cat = CIdent
|
||||||
|
type Type = Exp
|
||||||
|
|
||||||
|
mkFun, mkCat :: String -> String -> Fun
|
||||||
|
mkFun m f = CIQ (A.identC m) (A.identC f)
|
||||||
|
mkCat = mkFun
|
||||||
|
|
||||||
|
mkFunC, mkCatC :: String -> Fun
|
||||||
|
mkFunC s = let (m,f) = span (/= '.') s in mkFun m (drop 1 f)
|
||||||
|
mkCatC = mkFunC
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
167
src/GF/Canon/CanonToGrammar.hs
Normal file
167
src/GF/Canon/CanonToGrammar.hs
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
module CanonToGrammar where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
import MkGFC
|
||||||
|
---import CMacros
|
||||||
|
import qualified Modules as M
|
||||||
|
import qualified Option as O
|
||||||
|
import qualified Grammar as G
|
||||||
|
import qualified Macros as F
|
||||||
|
|
||||||
|
import Ident
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- a decompiler. AR 12/6/2003
|
||||||
|
|
||||||
|
canon2sourceModule :: CanonModule -> Err G.SourceModule
|
||||||
|
canon2sourceModule (i,mi) = do
|
||||||
|
i' <- redIdent i
|
||||||
|
info' <- case mi of
|
||||||
|
M.ModMod m -> do
|
||||||
|
(e,os) <- redExtOpen m
|
||||||
|
flags <- mapM redFlag $ M.flags m
|
||||||
|
(abstr,mt) <- case M.mtype m of
|
||||||
|
M.MTConcrete a -> do
|
||||||
|
a' <- redIdent a
|
||||||
|
return (a', M.MTConcrete a')
|
||||||
|
M.MTAbstract -> return (i',M.MTAbstract) --- c' not needed
|
||||||
|
M.MTResource -> return (i',M.MTResource) --- c' not needed
|
||||||
|
defs <- mapMTree redInfo $ M.jments m
|
||||||
|
return $ M.ModMod $ M.Module mt flags e os defs
|
||||||
|
_ -> Bad $ "cannot decompile module type"
|
||||||
|
return (i',info')
|
||||||
|
where
|
||||||
|
redExtOpen m = do
|
||||||
|
e' <- case M.extends m of
|
||||||
|
Just e -> liftM Just $ redIdent e
|
||||||
|
_ -> return Nothing
|
||||||
|
os' <- mapM (\ (M.OSimple i) -> liftM (\i -> M.OQualif i i) (redIdent i)) $
|
||||||
|
M.opens m
|
||||||
|
return (e',os')
|
||||||
|
|
||||||
|
redInfo :: (Ident,Info) -> Err (Ident,G.Info)
|
||||||
|
redInfo (c,info) = errIn ("decompiling abstract" +++ show c) $ do
|
||||||
|
c' <- redIdent c
|
||||||
|
info' <- case info of
|
||||||
|
AbsCat cont fs -> do
|
||||||
|
return $ G.AbsCat (Yes cont) (Yes fs)
|
||||||
|
AbsFun typ df -> do
|
||||||
|
return $ G.AbsFun (Yes typ) (Yes df)
|
||||||
|
|
||||||
|
ResPar par -> liftM (G.ResParam . Yes) $ mapM redParam par
|
||||||
|
|
||||||
|
CncCat pty ptr ppr -> do
|
||||||
|
ty' <- redCType pty
|
||||||
|
trm' <- redCTerm ptr
|
||||||
|
ppr' <- redCTerm ppr
|
||||||
|
return $ G.CncCat (Yes ty') (Yes trm') (Yes ppr')
|
||||||
|
CncFun (CIQ abstr cat) xx body ppr -> do
|
||||||
|
xx' <- mapM redArgVar xx
|
||||||
|
body' <- redCTerm body
|
||||||
|
ppr' <- redCTerm ppr
|
||||||
|
return $ G.CncFun Nothing (Yes (F.mkAbs xx' body')) (Yes ppr')
|
||||||
|
|
||||||
|
AnyInd b c -> liftM (G.AnyInd b) $ redIdent c
|
||||||
|
|
||||||
|
return (c',info')
|
||||||
|
|
||||||
|
redQIdent :: CIdent -> Err G.QIdent
|
||||||
|
redQIdent (CIQ m c) = liftM2 (,) (redIdent m) (redIdent c)
|
||||||
|
|
||||||
|
redIdent :: Ident -> Err Ident
|
||||||
|
redIdent = return
|
||||||
|
|
||||||
|
redFlag :: Flag -> Err O.Option
|
||||||
|
redFlag (Flg f x) = return $ O.Opt (prIdent f,[prIdent x])
|
||||||
|
|
||||||
|
redDecl :: Decl -> Err G.Decl
|
||||||
|
redDecl (Decl x a) = liftM2 (,) (redIdent x) (redTerm a)
|
||||||
|
|
||||||
|
redType :: Exp -> Err G.Type
|
||||||
|
redType = redTerm
|
||||||
|
|
||||||
|
redTerm :: Exp -> Err G.Term
|
||||||
|
redTerm t = return $ trExp t
|
||||||
|
|
||||||
|
-- resource
|
||||||
|
|
||||||
|
redParam (ParD c cont) = do
|
||||||
|
c' <- redIdent c
|
||||||
|
cont' <- mapM redCType cont
|
||||||
|
return $ (c', [(IW,t) | t <- cont'])
|
||||||
|
|
||||||
|
-- concrete syntax
|
||||||
|
|
||||||
|
redCType :: CType -> Err G.Type
|
||||||
|
redCType t = case t of
|
||||||
|
RecType lbs -> do
|
||||||
|
let (ls,ts) = unzip [(l,t) | Lbg l t <- lbs]
|
||||||
|
ls' = map redLabel ls
|
||||||
|
ts' <- mapM redCType ts
|
||||||
|
return $ G.RecType $ zip ls' ts'
|
||||||
|
Table p v -> liftM2 G.Table (redCType p) (redCType v)
|
||||||
|
Cn mc -> liftM (uncurry G.QC) $ redQIdent mc
|
||||||
|
TStr -> return $ F.typeStr
|
||||||
|
|
||||||
|
redCTerm :: Term -> Err G.Term
|
||||||
|
redCTerm x = case x of
|
||||||
|
Arg argvar -> liftM G.Vr $ redArgVar argvar
|
||||||
|
I cident -> liftM (uncurry G.Q) $ redQIdent cident
|
||||||
|
Con cident terms -> liftM2 F.mkApp
|
||||||
|
(liftM (uncurry G.QC) $ redQIdent cident)
|
||||||
|
(mapM redCTerm terms)
|
||||||
|
LI id -> liftM G.Vr $ redIdent id
|
||||||
|
R assigns -> do
|
||||||
|
let (ls,ts) = unzip [(l,t) | Ass l t <- assigns]
|
||||||
|
let ls' = map redLabel ls
|
||||||
|
ts' <- mapM redCTerm ts
|
||||||
|
return $ G.R [(l,(Nothing,t)) | (l,t) <- zip ls' ts']
|
||||||
|
P term label -> liftM2 G.P (redCTerm term) (return $ redLabel label)
|
||||||
|
T ctype cases -> do
|
||||||
|
ctype' <- redCType ctype
|
||||||
|
let (ps,ts) = unzip [(p,t) | Cas ps t <- cases, p <- ps] --- destroys sharing
|
||||||
|
ps' <- mapM redPatt ps
|
||||||
|
ts' <- mapM redCTerm ts --- duplicates work for shared rhss
|
||||||
|
let tinfo = case ps' of
|
||||||
|
[G.PV _] -> G.TTyped ctype'
|
||||||
|
_ -> G.TComp ctype'
|
||||||
|
return $ G.T tinfo $ zip ps' ts'
|
||||||
|
S term0 term -> liftM2 G.S (redCTerm term0) (redCTerm term)
|
||||||
|
C term0 term -> liftM2 G.C (redCTerm term0) (redCTerm term)
|
||||||
|
FV terms -> liftM G.FV $ mapM redCTerm terms
|
||||||
|
K (KS str) -> return $ G.K str
|
||||||
|
E -> return $ G.Empty
|
||||||
|
K (KP d vs) -> return $
|
||||||
|
G.Alts (tList d,[(tList s, G.Strs $ map G.K v) | Var s v <- vs])
|
||||||
|
where
|
||||||
|
tList ss = case ss of --- this should be in Macros
|
||||||
|
[] -> G.Empty
|
||||||
|
_ -> foldr1 G.C $ map G.K ss
|
||||||
|
|
||||||
|
failure x = Bad $ "not yet" +++ show x ----
|
||||||
|
|
||||||
|
redArgVar :: ArgVar -> Err Ident
|
||||||
|
redArgVar x = case x of
|
||||||
|
A x i -> return $ IA (prIdent x, fromInteger i)
|
||||||
|
AB x b i -> return $ IAV (prIdent x, fromInteger b, fromInteger i)
|
||||||
|
|
||||||
|
redLabel :: Label -> G.Label
|
||||||
|
redLabel (L x) = G.LIdent $ prIdent x
|
||||||
|
redLabel (LV i) = G.LVar $ fromInteger i
|
||||||
|
|
||||||
|
redPatt :: Patt -> Err G.Patt
|
||||||
|
redPatt p = case p of
|
||||||
|
PV x -> liftM G.PV $ redIdent x
|
||||||
|
PC mc ps -> do
|
||||||
|
(m,c) <- redQIdent mc
|
||||||
|
liftM (G.PP m c) (mapM redPatt ps)
|
||||||
|
PR rs -> do
|
||||||
|
let (ls,ts) = unzip [(l,t) | PAss l t <- rs]
|
||||||
|
ls' = map redLabel ls
|
||||||
|
ts <- mapM redPatt ts
|
||||||
|
return $ G.PR $ zip ls' ts
|
||||||
|
_ -> Bad $ "cannot recompile pattern" +++ show p
|
||||||
|
|
||||||
48
src/GF/Canon/GFC.hs
Normal file
48
src/GF/Canon/GFC.hs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
module GFC where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import PrintGFC
|
||||||
|
import qualified Abstract as A
|
||||||
|
|
||||||
|
import Ident
|
||||||
|
import Option
|
||||||
|
import Zipper
|
||||||
|
import Operations
|
||||||
|
import qualified Modules as M
|
||||||
|
|
||||||
|
import Char
|
||||||
|
|
||||||
|
-- canonical GF. AR 10/9/2002 -- 9/5/2003 -- 21/9
|
||||||
|
|
||||||
|
type Context = [(Ident,Exp)]
|
||||||
|
|
||||||
|
type CanonGrammar = M.MGrammar Ident Flag Info
|
||||||
|
|
||||||
|
type CanonModInfo = M.ModInfo Ident Flag Info
|
||||||
|
|
||||||
|
type CanonModule = (Ident, CanonModInfo)
|
||||||
|
|
||||||
|
type CanonAbs = M.Module Ident Option Info
|
||||||
|
|
||||||
|
data Info =
|
||||||
|
AbsCat A.Context [A.Fun]
|
||||||
|
| AbsFun A.Type A.Term
|
||||||
|
|
||||||
|
| ResPar [ParDef]
|
||||||
|
| ResOper CType Term -- global constant
|
||||||
|
| CncCat CType Term Printname
|
||||||
|
| CncFun CIdent [ArgVar] Term Printname
|
||||||
|
| AnyInd Bool Ident
|
||||||
|
deriving (Show)
|
||||||
|
|
||||||
|
type Printname = Term
|
||||||
|
|
||||||
|
-- some printing ----
|
||||||
|
|
||||||
|
{-
|
||||||
|
prCanonModInfo :: (Ident,CanonModInfo) -> String
|
||||||
|
prCanonModInfo = printTree . info2mod
|
||||||
|
|
||||||
|
prGrammar :: CanonGrammar -> String
|
||||||
|
prGrammar = printTree . grammar2canon
|
||||||
|
-}
|
||||||
22
src/GF/Canon/GetGFC.hs
Normal file
22
src/GF/Canon/GetGFC.hs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
module GetGFC where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import ParGFC
|
||||||
|
import GFC
|
||||||
|
import MkGFC
|
||||||
|
import Modules
|
||||||
|
import GetGrammar (err2err) ---
|
||||||
|
import UseIO
|
||||||
|
|
||||||
|
getCanonModule :: FilePath -> IOE CanonModule
|
||||||
|
getCanonModule file = do
|
||||||
|
gr <- getCanonGrammar file
|
||||||
|
case modules gr of
|
||||||
|
[m] -> return m
|
||||||
|
_ -> ioeErr $ Bad "expected exactly one module in a file"
|
||||||
|
|
||||||
|
getCanonGrammar :: FilePath -> IOE CanonGrammar
|
||||||
|
getCanonGrammar file = do
|
||||||
|
s <- ioeIO $ readFileIf file
|
||||||
|
c <- ioeErr $ err2err $ pCanon $ myLexer s
|
||||||
|
return $ canon2grammar c
|
||||||
105
src/GF/Canon/LexGFC.hs
Normal file
105
src/GF/Canon/LexGFC.hs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
module LexGFC where
|
||||||
|
|
||||||
|
import Alex
|
||||||
|
import ErrM
|
||||||
|
|
||||||
|
pTSpec p = PT p . TS
|
||||||
|
|
||||||
|
ident p = PT p . eitherResIdent TV
|
||||||
|
|
||||||
|
string p = PT p . TL . unescapeInitTail
|
||||||
|
|
||||||
|
int p = PT p . TI
|
||||||
|
|
||||||
|
|
||||||
|
data Tok =
|
||||||
|
TS String -- reserved words
|
||||||
|
| TL String -- string literals
|
||||||
|
| TI String -- integer literals
|
||||||
|
| TV String -- identifiers
|
||||||
|
| TD String -- double precision float literals
|
||||||
|
| TC String -- character literals
|
||||||
|
|
||||||
|
deriving (Eq,Show)
|
||||||
|
|
||||||
|
data Token =
|
||||||
|
PT Posn Tok
|
||||||
|
| Err Posn
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
tokenPos (PT (Pn _ l _) _ :_) = "line " ++ show l
|
||||||
|
tokenPos (Err (Pn _ l _) :_) = "line " ++ show l
|
||||||
|
tokenPos _ = "end of file"
|
||||||
|
|
||||||
|
prToken t = case t of
|
||||||
|
PT _ (TS s) -> s
|
||||||
|
PT _ (TI s) -> s
|
||||||
|
PT _ (TV s) -> s
|
||||||
|
PT _ (TD s) -> s
|
||||||
|
PT _ (TC s) -> s
|
||||||
|
_ -> show t
|
||||||
|
|
||||||
|
tokens:: String -> [Token]
|
||||||
|
tokens inp = scan tokens_scan inp
|
||||||
|
|
||||||
|
tokens_scan:: Scan Token
|
||||||
|
tokens_scan = load_scan (tokens_acts,stop_act) tokens_lx
|
||||||
|
where
|
||||||
|
stop_act p "" = []
|
||||||
|
stop_act p inp = [Err p]
|
||||||
|
|
||||||
|
eitherResIdent :: (String -> Tok) -> String -> Tok
|
||||||
|
eitherResIdent tv s = if isResWord s then (TS s) else (tv s) where
|
||||||
|
isResWord s = isInTree s $
|
||||||
|
B "lin" (B "concrete" (B "abstract" (B "Type" (B "Str" N N) N) (B "cat" N N)) (B "fun" (B "flags" (B "data" N N) N) (B "in" N N))) (B "param" (B "open" (B "of" (B "lincat" N N) N) (B "oper" N N)) (B "table" (B "resource" (B "pre" N N) N) (B "variants" N N)))
|
||||||
|
|
||||||
|
data BTree = N | B String BTree BTree deriving (Show)
|
||||||
|
|
||||||
|
isInTree :: String -> BTree -> Bool
|
||||||
|
isInTree x tree = case tree of
|
||||||
|
N -> False
|
||||||
|
B a left right
|
||||||
|
| x < a -> isInTree x left
|
||||||
|
| x > a -> isInTree x right
|
||||||
|
| x == a -> True
|
||||||
|
|
||||||
|
unescapeInitTail :: String -> String
|
||||||
|
unescapeInitTail = unesc . tail where
|
||||||
|
unesc s = case s of
|
||||||
|
'\\':c:cs | elem c ['\"', '\\', '\''] -> c : unesc cs
|
||||||
|
'\\':'n':cs -> '\n' : unesc cs
|
||||||
|
'\\':'t':cs -> '\t' : unesc cs
|
||||||
|
'"':[] -> []
|
||||||
|
c:cs -> c : unesc cs
|
||||||
|
_ -> []
|
||||||
|
|
||||||
|
tokens_acts = [("ident",ident),("int",int),("pTSpec",pTSpec),("string",string)]
|
||||||
|
|
||||||
|
tokens_lx :: [(Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))]
|
||||||
|
tokens_lx = [lx__0_0,lx__1_0,lx__2_0,lx__3_0,lx__4_0,lx__5_0,lx__6_0,lx__7_0,lx__8_0,lx__9_0,lx__10_0,lx__11_0]
|
||||||
|
lx__0_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__0_0 = (False,[],-1,(('\t','\255'),[('\t',1),('\n',1),('\v',1),('\f',1),('\r',1),(' ',1),('!',6),('"',8),('$',6),('(',6),(')',6),('*',2),('+',5),(',',6),('-',3),('.',6),('/',6),('0',11),('1',11),('2',11),('3',11),('4',11),('5',11),('6',11),('7',11),('8',11),('9',11),(':',6),(';',6),('<',6),('=',4),('>',6),('?',6),('@',6),('A',7),('B',7),('C',7),('D',7),('E',7),('F',7),('G',7),('H',7),('I',7),('J',7),('K',7),('L',7),('M',7),('N',7),('O',7),('P',7),('Q',7),('R',7),('S',7),('T',7),('U',7),('V',7),('W',7),('X',7),('Y',7),('Z',7),('[',6),('\\',6),(']',6),('_',6),('a',7),('b',7),('c',7),('d',7),('e',7),('f',7),('g',7),('h',7),('i',7),('j',7),('k',7),('l',7),('m',7),('n',7),('o',7),('p',7),('q',7),('r',7),('s',7),('t',7),('u',7),('v',7),('w',7),('x',7),('y',7),('z',7),('{',6),('|',6),('}',6),('\192',7),('\193',7),('\194',7),('\195',7),('\196',7),('\197',7),('\198',7),('\199',7),('\200',7),('\201',7),('\202',7),('\203',7),('\204',7),('\205',7),('\206',7),('\207',7),('\208',7),('\209',7),('\210',7),('\211',7),('\212',7),('\213',7),('\214',7),('\216',7),('\217',7),('\218',7),('\219',7),('\220',7),('\221',7),('\222',7),('\223',7),('\224',7),('\225',7),('\226',7),('\227',7),('\228',7),('\229',7),('\230',7),('\231',7),('\232',7),('\233',7),('\234',7),('\235',7),('\236',7),('\237',7),('\238',7),('\239',7),('\240',7),('\241',7),('\242',7),('\243',7),('\244',7),('\245',7),('\246',7),('\248',7),('\249',7),('\250',7),('\251',7),('\252',7),('\253',7),('\254',7),('\255',7)]))
|
||||||
|
lx__1_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__1_0 = (True,[(0,"",[],Nothing,Nothing)],-1,(('\t',' '),[('\t',1),('\n',1),('\v',1),('\f',1),('\r',1),(' ',1)]))
|
||||||
|
lx__2_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__2_0 = (False,[],-1,(('*','*'),[('*',6)]))
|
||||||
|
lx__3_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__3_0 = (False,[],-1,(('>','>'),[('>',6)]))
|
||||||
|
lx__4_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__4_0 = (True,[(1,"pTSpec",[],Nothing,Nothing)],-1,(('>','>'),[('>',6)]))
|
||||||
|
lx__5_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__5_0 = (True,[(1,"pTSpec",[],Nothing,Nothing)],-1,(('+','+'),[('+',6)]))
|
||||||
|
lx__6_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__6_0 = (True,[(1,"pTSpec",[],Nothing,Nothing)],-1,(('0','0'),[]))
|
||||||
|
lx__7_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__7_0 = (True,[(2,"ident",[],Nothing,Nothing)],-1,(('\'','\255'),[('\'',7),('0',7),('1',7),('2',7),('3',7),('4',7),('5',7),('6',7),('7',7),('8',7),('9',7),('A',7),('B',7),('C',7),('D',7),('E',7),('F',7),('G',7),('H',7),('I',7),('J',7),('K',7),('L',7),('M',7),('N',7),('O',7),('P',7),('Q',7),('R',7),('S',7),('T',7),('U',7),('V',7),('W',7),('X',7),('Y',7),('Z',7),('_',7),('a',7),('b',7),('c',7),('d',7),('e',7),('f',7),('g',7),('h',7),('i',7),('j',7),('k',7),('l',7),('m',7),('n',7),('o',7),('p',7),('q',7),('r',7),('s',7),('t',7),('u',7),('v',7),('w',7),('x',7),('y',7),('z',7),('\192',7),('\193',7),('\194',7),('\195',7),('\196',7),('\197',7),('\198',7),('\199',7),('\200',7),('\201',7),('\202',7),('\203',7),('\204',7),('\205',7),('\206',7),('\207',7),('\208',7),('\209',7),('\210',7),('\211',7),('\212',7),('\213',7),('\214',7),('\216',7),('\217',7),('\218',7),('\219',7),('\220',7),('\221',7),('\222',7),('\223',7),('\224',7),('\225',7),('\226',7),('\227',7),('\228',7),('\229',7),('\230',7),('\231',7),('\232',7),('\233',7),('\234',7),('\235',7),('\236',7),('\237',7),('\238',7),('\239',7),('\240',7),('\241',7),('\242',7),('\243',7),('\244',7),('\245',7),('\246',7),('\248',7),('\249',7),('\250',7),('\251',7),('\252',7),('\253',7),('\254',7),('\255',7)]))
|
||||||
|
lx__8_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__8_0 = (False,[],8,(('\n','\\'),[('\n',-1),('"',10),('\\',9)]))
|
||||||
|
lx__9_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__9_0 = (False,[],-1,(('"','t'),[('"',8),('\'',8),('\\',8),('n',8),('t',8)]))
|
||||||
|
lx__10_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__10_0 = (True,[(3,"string",[],Nothing,Nothing)],-1,(('0','0'),[]))
|
||||||
|
lx__11_0 :: (Bool, [(Int,String,[Int],Maybe((Char,Char),[(Char,Bool)]),Maybe Int)], Int, ((Char,Char),[(Char,Int)]))
|
||||||
|
lx__11_0 = (True,[(4,"int",[],Nothing,Nothing)],-1,(('0','9'),[('0',11),('1',11),('2',11),('3',11),('4',11),('5',11),('6',11),('7',11),('8',11),('9',11)]))
|
||||||
|
|
||||||
141
src/GF/Canon/Look.hs
Normal file
141
src/GF/Canon/Look.hs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
module Look where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
import PrGrammar
|
||||||
|
import CMacros
|
||||||
|
----import Values
|
||||||
|
import MMacros
|
||||||
|
import qualified Modules as M
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
import List
|
||||||
|
|
||||||
|
-- lookup in GFC. AR 2003
|
||||||
|
|
||||||
|
-- linearization lookup
|
||||||
|
|
||||||
|
lookupCncInfo :: CanonGrammar -> CIdent -> Err Info
|
||||||
|
lookupCncInfo gr f@(CIQ m c) = do
|
||||||
|
mt <- M.lookupModule gr m
|
||||||
|
case mt of
|
||||||
|
M.ModMod a -> errIn ("module" +++ prt m) $
|
||||||
|
lookupTree prt c $ M.jments a
|
||||||
|
_ -> prtBad "not concrete module" m
|
||||||
|
|
||||||
|
lookupLin :: CanonGrammar -> CIdent -> Err Term
|
||||||
|
lookupLin gr f = do
|
||||||
|
info <- lookupCncInfo gr f
|
||||||
|
case info of
|
||||||
|
CncFun _ _ t _ -> return t
|
||||||
|
CncCat _ t _ -> return t
|
||||||
|
AnyInd _ n -> lookupLin gr $ redirectIdent n f
|
||||||
|
|
||||||
|
lookupResInfo :: CanonGrammar -> CIdent -> Err Info
|
||||||
|
lookupResInfo gr f@(CIQ m c) = do
|
||||||
|
mt <- M.lookupModule gr m
|
||||||
|
case mt of
|
||||||
|
M.ModMod a -> lookupTree prt c $ M.jments a
|
||||||
|
_ -> prtBad "not resource module" m
|
||||||
|
|
||||||
|
lookupGlobal :: CanonGrammar -> CIdent -> Err Term
|
||||||
|
lookupGlobal gr f = do
|
||||||
|
info <- lookupResInfo gr f
|
||||||
|
case info of
|
||||||
|
ResOper _ t -> return t
|
||||||
|
AnyInd _ n -> lookupGlobal gr $ redirectIdent n f
|
||||||
|
_ -> prtBad "cannot find global" f
|
||||||
|
|
||||||
|
lookupParamValues :: CanonGrammar -> CIdent -> Err [Term]
|
||||||
|
lookupParamValues gr pt@(CIQ m _) = do
|
||||||
|
info <- lookupResInfo gr pt
|
||||||
|
case info of
|
||||||
|
ResPar ps -> liftM concat $ mapM mkPar ps
|
||||||
|
AnyInd _ n -> lookupParamValues gr $ redirectIdent n pt
|
||||||
|
_ -> prtBad "cannot find parameter type" pt
|
||||||
|
where
|
||||||
|
mkPar (ParD f co) = do
|
||||||
|
vs <- liftM combinations $ mapM (allParamValues gr) co
|
||||||
|
return $ map (Con (CIQ m f)) vs
|
||||||
|
|
||||||
|
-- this is needed since param type can also be a record type
|
||||||
|
|
||||||
|
allParamValues :: CanonGrammar -> CType -> Err [Term]
|
||||||
|
allParamValues cnc ptyp = case ptyp of
|
||||||
|
Cn pc -> lookupParamValues cnc pc
|
||||||
|
RecType r -> do
|
||||||
|
let (ls,tys) = unzip [(l,t) | Lbg l t <- r]
|
||||||
|
tss <- mapM allPV tys
|
||||||
|
return [R (map (uncurry Ass) (zip ls ts)) | ts <- combinations tss]
|
||||||
|
_ -> prtBad "cannot possibly find parameter values for" ptyp
|
||||||
|
where
|
||||||
|
allPV = allParamValues cnc
|
||||||
|
|
||||||
|
-- runtime computation on GFC objects
|
||||||
|
|
||||||
|
ccompute :: CanonGrammar -> [Term] -> Term -> Err Term
|
||||||
|
ccompute cnc = comp []
|
||||||
|
where
|
||||||
|
comp g xs t = case t of
|
||||||
|
Arg (A _ i) -> errIn ("argument list") $ xs !? fromInteger i
|
||||||
|
Arg (AB _ _ i) -> errIn ("argument list for binding") $ xs !? fromInteger i
|
||||||
|
I c -> look c
|
||||||
|
LI c -> lookVar c g
|
||||||
|
|
||||||
|
-- short-cut computation of selections: compute the table only if needed
|
||||||
|
S u v -> do
|
||||||
|
u' <- compt u
|
||||||
|
case u' of
|
||||||
|
T _ [Cas [PW] b] -> compt b
|
||||||
|
T _ [Cas [PV x] b] -> do
|
||||||
|
v' <- compt v
|
||||||
|
comp ((x,v') : g) xs b
|
||||||
|
T _ cs -> do
|
||||||
|
v' <- compt v
|
||||||
|
if noVar v'
|
||||||
|
then matchPatt cs v' >>= compt
|
||||||
|
else return $ S u' v'
|
||||||
|
|
||||||
|
_ -> liftM (S u') $ compt v
|
||||||
|
|
||||||
|
P u l -> do
|
||||||
|
u' <- compt u
|
||||||
|
case u' of
|
||||||
|
R rs -> maybe (Bad ("unknown label" +++ prt l +++ "in" +++ prt u'))
|
||||||
|
return $
|
||||||
|
lookup l [ (x,y) | Ass x y <- rs]
|
||||||
|
_ -> return $ P u' l
|
||||||
|
FV ts -> liftM FV (mapM compt ts)
|
||||||
|
C E b -> compt b
|
||||||
|
C a E -> compt a
|
||||||
|
C a b -> do
|
||||||
|
a' <- compt a
|
||||||
|
b' <- compt b
|
||||||
|
return $ case (a',b') of
|
||||||
|
(E,_) -> b'
|
||||||
|
(_,E) -> a'
|
||||||
|
_ -> C a' b'
|
||||||
|
R rs -> liftM (R . map (uncurry Ass)) $
|
||||||
|
mapPairsM compt [(l,r) | Ass l r <- rs]
|
||||||
|
|
||||||
|
-- only expand the table when the table is really needed: use expandLin
|
||||||
|
T ty rs -> liftM (T ty . map (uncurry Cas)) $
|
||||||
|
mapPairsM compt [(l,r) | Cas l r <- rs]
|
||||||
|
|
||||||
|
Con c xs -> liftM (Con c) $ mapM compt xs
|
||||||
|
|
||||||
|
_ -> return t
|
||||||
|
where
|
||||||
|
compt = comp g xs
|
||||||
|
look c = lookupGlobal cnc c
|
||||||
|
|
||||||
|
lookVar c co = case lookup c co of
|
||||||
|
Just t -> return t
|
||||||
|
_ -> return $ LI c --- Bad $ "unknown local variable" +++ prt c ---
|
||||||
|
|
||||||
|
noVar v = case v of
|
||||||
|
LI _ -> False
|
||||||
|
R rs -> all noVar [t | Ass _ t <- rs]
|
||||||
|
_ -> True --- other cases?
|
||||||
121
src/GF/Canon/MkGFC.hs
Normal file
121
src/GF/Canon/MkGFC.hs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
module MkGFC where
|
||||||
|
|
||||||
|
import GFC
|
||||||
|
import AbsGFC
|
||||||
|
import qualified Abstract as A
|
||||||
|
import PrGrammar
|
||||||
|
|
||||||
|
import Ident
|
||||||
|
import Operations
|
||||||
|
import qualified Modules as M
|
||||||
|
|
||||||
|
prCanonModInfo :: CanonModule -> String
|
||||||
|
prCanonModInfo = prt . info2mod
|
||||||
|
|
||||||
|
canon2grammar :: Canon -> CanonGrammar
|
||||||
|
canon2grammar (Gr modules) = M.MGrammar $ map mod2info modules where
|
||||||
|
mod2info m = case m of
|
||||||
|
Mod mt e os flags defs ->
|
||||||
|
let defs' = buildTree $ map def2info defs
|
||||||
|
(a,mt') = case mt of
|
||||||
|
MTAbs a -> (a,M.MTAbstract)
|
||||||
|
MTRes a -> (a,M.MTResource)
|
||||||
|
MTCnc a x -> (a,M.MTConcrete x)
|
||||||
|
in (a,M.ModMod (M.Module mt' flags (ee e) (oo os) defs'))
|
||||||
|
ee (Ext m) = Just m
|
||||||
|
ee _ = Nothing
|
||||||
|
oo (Opens ms) = map M.OSimple ms
|
||||||
|
oo _ = []
|
||||||
|
|
||||||
|
grammar2canon :: CanonGrammar -> Canon
|
||||||
|
grammar2canon (M.MGrammar modules) = Gr $ map info2mod modules
|
||||||
|
|
||||||
|
info2mod m = case m of
|
||||||
|
(a, M.ModMod (M.Module mt flags me os defs)) ->
|
||||||
|
let defs' = map info2def $ tree2list defs
|
||||||
|
mt' = case mt of
|
||||||
|
M.MTAbstract -> MTAbs a
|
||||||
|
M.MTResource -> MTRes a
|
||||||
|
M.MTConcrete x -> MTCnc a x
|
||||||
|
in
|
||||||
|
Mod mt' (gfcE me) (gfcO os) flags defs'
|
||||||
|
where
|
||||||
|
gfcE = maybe NoExt Ext
|
||||||
|
gfcO os = if null os then NoOpens else Opens [m | M.OSimple m <- os]
|
||||||
|
|
||||||
|
|
||||||
|
-- these translations are meant to be trivial
|
||||||
|
|
||||||
|
defs2infos = sorted2tree . map def2info
|
||||||
|
|
||||||
|
def2info d = case d of
|
||||||
|
AbsDCat c cont fs -> (c,AbsCat (trCont cont) (trFs fs))
|
||||||
|
AbsDFun c ty df -> (c,AbsFun (trExp ty) (trExp df))
|
||||||
|
ResDPar c df -> (c,ResPar df)
|
||||||
|
ResDOper c ty df -> (c,ResOper ty df)
|
||||||
|
CncDCat c ty df pr -> (c, CncCat ty df pr)
|
||||||
|
CncDFun f c xs li pr -> (f, CncFun c xs li pr)
|
||||||
|
AnyDInd c b m -> (c, AnyInd (b == Canon) m)
|
||||||
|
|
||||||
|
-- from file to internal
|
||||||
|
|
||||||
|
trCont cont = [(x,trExp t) | Decl x t <- cont]
|
||||||
|
|
||||||
|
trFs = map trQIdent
|
||||||
|
|
||||||
|
trExp t = case t of
|
||||||
|
EProd x a b -> A.Prod x (trExp a) (trExp b)
|
||||||
|
EAbs x b -> A.Abs x (trExp b)
|
||||||
|
EApp f a -> A.App (trExp f) (trExp a)
|
||||||
|
EEq _ -> A.Eqs [] ---- eqs
|
||||||
|
_ -> trAt t
|
||||||
|
where
|
||||||
|
trAt (EAtom t) = case t of
|
||||||
|
AC c -> (uncurry A.Q) $ trQIdent c
|
||||||
|
AD c -> (uncurry A.QC) $ trQIdent c
|
||||||
|
AV v -> A.Vr v
|
||||||
|
AM i -> A.Meta $ A.MetaSymb $ fromInteger i
|
||||||
|
AT s -> A.Sort $ prt s
|
||||||
|
AS s -> A.K s
|
||||||
|
AI i -> A.EInt $ fromInteger i
|
||||||
|
|
||||||
|
trQIdent (CIQ m c) = (m,c)
|
||||||
|
|
||||||
|
-- from internal to file
|
||||||
|
|
||||||
|
infos2defs = map info2def . tree2list
|
||||||
|
|
||||||
|
info2def d = case d of
|
||||||
|
(c,AbsCat cont fs) -> AbsDCat c (rtCont cont) (rtFs fs)
|
||||||
|
(c,AbsFun ty df) -> AbsDFun c (rtExp ty) (rtExp df)
|
||||||
|
(c,ResPar df) -> ResDPar c df
|
||||||
|
(c,ResOper ty df) -> ResDOper c ty df
|
||||||
|
(c,CncCat ty df pr) -> CncDCat c ty df pr
|
||||||
|
(f,CncFun c xs li pr) -> CncDFun f c xs li pr
|
||||||
|
(c,AnyInd b m) -> AnyDInd c (if b then Canon else NonCan) m
|
||||||
|
|
||||||
|
rtCont cont = [Decl (rtIdent x) (rtExp t) | (x,t) <- cont]
|
||||||
|
|
||||||
|
rtFs = map rtQIdent
|
||||||
|
|
||||||
|
rtExp t = case t of
|
||||||
|
A.Prod x a b -> EProd (rtIdent x) (rtExp a) (rtExp b)
|
||||||
|
A.Abs x b -> EAbs (rtIdent x) (rtExp b)
|
||||||
|
A.App f a -> EApp (rtExp f) (rtExp a)
|
||||||
|
A.Eqs _ -> EEq [] ---- eqs
|
||||||
|
_ -> EAtom $ rtAt t
|
||||||
|
where
|
||||||
|
rtAt t = case t of
|
||||||
|
A.Q m c -> AC $ rtQIdent (m,c)
|
||||||
|
A.QC m c -> AD $ rtQIdent (m,c)
|
||||||
|
A.Vr v -> AV v
|
||||||
|
A.Meta i -> AM $ toInteger $ A.metaSymbInt i
|
||||||
|
A.Sort "Type" -> AT SType
|
||||||
|
A.K s -> AS s
|
||||||
|
A.EInt i -> AI $ toInteger i
|
||||||
|
_ -> error $ "MkGFC.rt not defined for" +++ show t
|
||||||
|
|
||||||
|
rtQIdent (m,c) = CIQ (rtIdent m) (rtIdent c)
|
||||||
|
rtIdent x
|
||||||
|
| isWildIdent x = identC "h_" --- needed in declarations
|
||||||
|
| otherwise = identC $ prt x ---
|
||||||
36
src/GF/Canon/PrExp.hs
Normal file
36
src/GF/Canon/PrExp.hs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
module PrExp where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import GFC
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
-- some printing
|
||||||
|
|
||||||
|
-- print trees without qualifications
|
||||||
|
|
||||||
|
prExp :: Exp -> String
|
||||||
|
prExp e = case e of
|
||||||
|
EApp f a -> pr1 f +++ pr2 a
|
||||||
|
EAbsR x b -> "\\" ++ prtt x +++ "->" +++ prExp b
|
||||||
|
EAbs x _ b -> prExp $ EAbsR x b
|
||||||
|
EProd x a b -> "(\\" ++ prtt x +++ ":" +++ prExp a ++ ")" +++ "->" +++ prExp b
|
||||||
|
EAtomR a -> prAtom a
|
||||||
|
EAtom a _ -> prAtom a
|
||||||
|
_ -> prtt e
|
||||||
|
where
|
||||||
|
pr1 e = case e of
|
||||||
|
EAbsR _ _ -> prParenth $ prExp e
|
||||||
|
EAbs _ _ _ -> prParenth $ prExp e
|
||||||
|
EProd _ _ _ -> prParenth $ prExp e
|
||||||
|
_ -> prExp e
|
||||||
|
pr2 e = case e of
|
||||||
|
EApp _ _ -> prParenth $ prExp e
|
||||||
|
_ -> pr1 e
|
||||||
|
|
||||||
|
prAtom a = case a of
|
||||||
|
AC c -> prCIdent c
|
||||||
|
AD c -> prCIdent c
|
||||||
|
_ -> prtt a
|
||||||
|
|
||||||
|
prCIdent (CIQ _ c) = prtt c
|
||||||
319
src/GF/Canon/PrintGFC.hs
Normal file
319
src/GF/Canon/PrintGFC.hs
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
module PrintGFC where
|
||||||
|
|
||||||
|
-- pretty-printer generated by the BNF converter, except handhacked spacing --H
|
||||||
|
|
||||||
|
import Ident --H
|
||||||
|
import AbsGFC
|
||||||
|
import Char
|
||||||
|
|
||||||
|
-- the top-level printing method
|
||||||
|
printTree :: Print a => a -> String
|
||||||
|
printTree = render . prt 0
|
||||||
|
|
||||||
|
-- you may want to change render and parenth
|
||||||
|
|
||||||
|
render :: [String] -> String
|
||||||
|
render = rend 0 where
|
||||||
|
rend i ss = case ss of
|
||||||
|
"NEW" :ts -> realnew $ rend i ts --H
|
||||||
|
"<" :ts -> cons "<" $ rend i ts --H
|
||||||
|
"$" :ts -> cons "$" $ rend i ts --H
|
||||||
|
"?" :ts -> cons "?" $ rend i ts --H
|
||||||
|
"[" :ts -> cons "[" $ rend i ts
|
||||||
|
"(" :ts -> cons "(" $ rend i ts
|
||||||
|
"{" :ts -> cons "{" $ new (i+1) $ rend (i+1) ts
|
||||||
|
"}" : ";":ts -> new (i-1) $ space "}" $ cons ";" $ new (i-1) $ rend (i-1) ts
|
||||||
|
"}" :ts -> new (i-1) $ cons "}" $ new (i-1) $ rend (i-1) ts
|
||||||
|
";" :ts -> cons ";" $ new i $ rend i ts
|
||||||
|
t : "," :ts -> cons t $ space "," $ rend i ts
|
||||||
|
t : ")" :ts -> cons t $ cons ")" $ rend i ts
|
||||||
|
t : "]" :ts -> cons t $ cons "]" $ rend i ts
|
||||||
|
t : ">" :ts -> cons t $ cons ">" $ rend i ts --H
|
||||||
|
t : "." :ts -> cons t $ cons "." $ rend i ts --H
|
||||||
|
t :ts -> realspace t $ rend i ts --H
|
||||||
|
_ -> ""
|
||||||
|
cons s t = s ++ t
|
||||||
|
space t s = t ++ " " ++ s --H
|
||||||
|
realspace t s = if null s then t else t ++ " " ++ s --H
|
||||||
|
new i s = s --H '\n' : replicate (2*i) ' ' ++ dropWhile isSpace s
|
||||||
|
realnew s = '\n':s --H
|
||||||
|
|
||||||
|
parenth :: [String] -> [String]
|
||||||
|
parenth ss = ["("] ++ ss ++ [")"]
|
||||||
|
|
||||||
|
-- the printer class does the job
|
||||||
|
class Print a where
|
||||||
|
prt :: Int -> a -> [String]
|
||||||
|
prtList :: [a] -> [String]
|
||||||
|
prtList = concat . map (prt 0)
|
||||||
|
|
||||||
|
instance Print a => Print [a] where
|
||||||
|
prt _ = prtList
|
||||||
|
|
||||||
|
instance Print Integer where
|
||||||
|
prt _ = (:[]) . show
|
||||||
|
|
||||||
|
instance Print Double where
|
||||||
|
prt _ = (:[]) . show
|
||||||
|
|
||||||
|
instance Print Char where
|
||||||
|
prt _ s = ["'" ++ mkEsc s ++ "'"]
|
||||||
|
prtList s = ["\"" ++ concatMap mkEsc s ++ "\""]
|
||||||
|
|
||||||
|
mkEsc s = case s of
|
||||||
|
_ | elem s "\\\"'" -> '\\':[s]
|
||||||
|
'\n' -> "\\n"
|
||||||
|
'\t' -> "\\t"
|
||||||
|
_ -> [s]
|
||||||
|
|
||||||
|
prPrec :: Int -> Int -> [String] -> [String]
|
||||||
|
prPrec i j = if j<i then parenth else id
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Ident where
|
||||||
|
prt _ i = [prIdent i]
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [","] , prt 0 xs])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Canon where
|
||||||
|
prt i e = case e of
|
||||||
|
Gr modules -> prPrec i 0 (concat [prt 0 modules])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Module where
|
||||||
|
prt i e = case e of
|
||||||
|
Mod modtype extend open flags defs -> prPrec i 0 (concat [prt 0 modtype , ["="] , prt 0 extend , prt 0 open , ["{"] , prt 0 flags , prt 0 defs , ["}"]])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print ModType where
|
||||||
|
prt i e = case e of
|
||||||
|
MTAbs id -> prPrec i 0 (concat [["abstract"] , prt 0 id])
|
||||||
|
MTCnc id0 id -> prPrec i 0 (concat [["concrete"] , prt 0 id0 , ["of"] , prt 0 id])
|
||||||
|
MTRes id -> prPrec i 0 (concat [["resource"] , prt 0 id])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Extend where
|
||||||
|
prt i e = case e of
|
||||||
|
Ext id -> prPrec i 0 (concat [prt 0 id , ["**"]])
|
||||||
|
NoExt -> prPrec i 0 (concat [])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Open where
|
||||||
|
prt i e = case e of
|
||||||
|
NoOpens -> prPrec i 0 (concat [])
|
||||||
|
Opens ids -> prPrec i 0 (concat [["open"] , prt 0 ids , ["in"]])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Flag where
|
||||||
|
prt i e = case e of
|
||||||
|
Flg id0 id -> prPrec i 0 (concat [["flags"] , prt 0 id0 , ["="] , prt 0 id])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Def where
|
||||||
|
prt i e = case e of
|
||||||
|
AbsDCat id decls cidents -> prPrec i 0 (concat [["cat"] , prt 0 id , ["["] , prt 0 decls , ["]"] , ["="] , prt 0 cidents])
|
||||||
|
AbsDFun id exp0 exp -> prPrec i 0 (concat [["fun"] , prt 0 id , [":"] , prt 0 exp0 , ["="] , prt 0 exp])
|
||||||
|
ResDPar id pardefs -> prPrec i 0 (concat [["param"] , prt 0 id , ["="] , prt 0 pardefs])
|
||||||
|
ResDOper id ctype term -> prPrec i 0 (concat [["oper"] , prt 0 id , [":"] , prt 0 ctype , ["="] , prt 0 term])
|
||||||
|
CncDCat id ctype term0 term -> prPrec i 0 (concat [["lincat"] , prt 0 id , ["="] , prt 0 ctype , ["="] , prt 0 term0 , [";"] , prt 0 term])
|
||||||
|
CncDFun id cident argvars term0 term -> prPrec i 0 (concat [["lin"] , prt 0 id , [":"] , prt 0 cident , ["="] , ["\\"] , prt 0 argvars , ["->"] , prt 0 term0 , [";"] , prt 0 term])
|
||||||
|
AnyDInd id0 status id -> prPrec i 0 (concat [prt 0 id0 , prt 0 status , ["in"] , prt 0 id])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , [";","NEW"] , prt 0 xs]) --H
|
||||||
|
|
||||||
|
instance Print ParDef where
|
||||||
|
prt i e = case e of
|
||||||
|
ParD id ctypes -> prPrec i 0 (concat [prt 0 id , prt 0 ctypes])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , ["|"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Status where
|
||||||
|
prt i e = case e of
|
||||||
|
Canon -> prPrec i 0 (concat [["data"]])
|
||||||
|
NonCan -> prPrec i 0 (concat [])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print CIdent where
|
||||||
|
prt i e = case e of
|
||||||
|
CIQ id0 id -> prPrec i 0 (concat [prt 0 id0 , ["."] , prt 0 id])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Exp where
|
||||||
|
prt i e = case e of
|
||||||
|
EApp exp0 exp -> prPrec i 1 (concat [prt 1 exp0 , prt 2 exp])
|
||||||
|
EProd id exp0 exp -> prPrec i 0 (concat [["("] , prt 0 id , [":"] , prt 0 exp0 , [")"] , ["->"] , prt 0 exp])
|
||||||
|
EAtom atom -> prPrec i 2 (concat [prt 0 atom])
|
||||||
|
EAbs id exp -> prPrec i 0 (concat [["\\"] , prt 0 id , ["->"] , prt 0 exp])
|
||||||
|
EEq equations -> prPrec i 0 (concat [["{"] , prt 0 equations , ["}"]])
|
||||||
|
|
||||||
|
instance Print Sort where
|
||||||
|
prt i e = case e of
|
||||||
|
SType -> prPrec i 0 (concat [["Type"]])
|
||||||
|
|
||||||
|
instance Print Equation where
|
||||||
|
prt i e = case e of
|
||||||
|
Equ apatts exp -> prPrec i 0 (concat [prt 0 apatts , ["->"] , prt 0 exp])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print APatt where
|
||||||
|
prt i e = case e of
|
||||||
|
APC cident apatts -> prPrec i 0 (concat [["("] , prt 0 cident , prt 0 apatts , [")"]])
|
||||||
|
APV id -> prPrec i 0 (concat [prt 0 id])
|
||||||
|
APS str -> prPrec i 0 (concat [prt 0 str])
|
||||||
|
API n -> prPrec i 0 (concat [prt 0 n])
|
||||||
|
APW -> prPrec i 0 (concat [["_"]])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Atom where
|
||||||
|
prt i e = case e of
|
||||||
|
AC cident -> prPrec i 0 (concat [prt 0 cident])
|
||||||
|
AD cident -> prPrec i 0 (concat [["<"] , prt 0 cident , [">"]])
|
||||||
|
AV id -> prPrec i 0 (concat [["$"] , prt 0 id])
|
||||||
|
AM n -> prPrec i 0 (concat [["?"] , prt 0 n])
|
||||||
|
AS str -> prPrec i 0 (concat [prt 0 str])
|
||||||
|
AI n -> prPrec i 0 (concat [prt 0 n])
|
||||||
|
AT sort -> prPrec i 0 (concat [prt 0 sort])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Decl where
|
||||||
|
prt i e = case e of
|
||||||
|
Decl id exp -> prPrec i 0 (concat [prt 0 id , [":"] , prt 0 exp])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print CType where
|
||||||
|
prt i e = case e of
|
||||||
|
RecType labellings -> prPrec i 0 (concat [["{"] , prt 0 labellings , ["}"]])
|
||||||
|
Table ctype0 ctype -> prPrec i 0 (concat [["("] , prt 0 ctype0 , ["=>"] , prt 0 ctype , [")"]])
|
||||||
|
Cn cident -> prPrec i 0 (concat [prt 0 cident])
|
||||||
|
TStr -> prPrec i 0 (concat [["Str"]])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Labelling where
|
||||||
|
prt i e = case e of
|
||||||
|
Lbg label ctype -> prPrec i 0 (concat [prt 0 label , [":"] , prt 0 ctype])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Term where
|
||||||
|
prt i e = case e of
|
||||||
|
Arg argvar -> prPrec i 2 (concat [prt 0 argvar])
|
||||||
|
I cident -> prPrec i 2 (concat [prt 0 cident])
|
||||||
|
Con cident terms -> prPrec i 2 (concat [["<"] , prt 0 cident , prt 2 terms , [">"]])
|
||||||
|
LI id -> prPrec i 2 (concat [["$"] , prt 0 id])
|
||||||
|
R assigns -> prPrec i 2 (concat [["{"] , prt 0 assigns , ["}"]])
|
||||||
|
P term label -> prPrec i 1 (concat [prt 2 term , ["."] , prt 0 label])
|
||||||
|
T ctype cases -> prPrec i 1 (concat [["table"] , prt 0 ctype , ["{"] , prt 0 cases , ["}"]])
|
||||||
|
S term0 term -> prPrec i 1 (concat [prt 1 term0 , ["!"] , prt 2 term])
|
||||||
|
C term0 term -> prPrec i 0 (concat [prt 0 term0 , ["++"] , prt 1 term])
|
||||||
|
FV terms -> prPrec i 1 (concat [["variants"] , ["{"] , prt 2 terms , ["}"]])
|
||||||
|
K tokn -> prPrec i 2 (concat [prt 0 tokn])
|
||||||
|
E -> prPrec i 2 (concat [["["] , ["]"]])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 2 x , prt 2 xs])
|
||||||
|
|
||||||
|
instance Print Tokn where
|
||||||
|
prt i e = case e of
|
||||||
|
KS str -> prPrec i 0 (concat [prt 0 str])
|
||||||
|
KP strs variants -> prPrec i 0 (concat [["["] , ["pre"] , prt 0 strs , ["{"] , prt 0 variants , ["}"] , ["]"]])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print Assign where
|
||||||
|
prt i e = case e of
|
||||||
|
Ass label term -> prPrec i 0 (concat [prt 0 label , ["="] , prt 0 term])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Case where
|
||||||
|
prt i e = case e of
|
||||||
|
Cas patts term -> prPrec i 0 (concat [prt 0 patts , ["=>"] , prt 0 term])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Variant where
|
||||||
|
prt i e = case e of
|
||||||
|
Var strs0 strs -> prPrec i 0 (concat [prt 0 strs0 , ["/"] , prt 0 strs])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Label where
|
||||||
|
prt i e = case e of
|
||||||
|
L id -> prPrec i 0 (concat [prt 0 id])
|
||||||
|
LV n -> prPrec i 0 (concat [["$"] , prt 0 n])
|
||||||
|
|
||||||
|
|
||||||
|
instance Print ArgVar where
|
||||||
|
prt i e = case e of
|
||||||
|
A id n -> prPrec i 0 (concat [prt 0 id , ["@"] , prt 0 n])
|
||||||
|
AB id n0 n -> prPrec i 0 (concat [prt 0 id , ["+"] , prt 0 n0 , ["@"] , prt 0 n])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [","] , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print Patt where
|
||||||
|
prt i e = case e of
|
||||||
|
PC cident patts -> prPrec i 0 (concat [["("] , prt 0 cident , prt 0 patts , [")"]])
|
||||||
|
PV id -> prPrec i 0 (concat [prt 0 id])
|
||||||
|
PW -> prPrec i 0 (concat [["_"]])
|
||||||
|
PR pattassigns -> prPrec i 0 (concat [["{"] , prt 0 pattassigns , ["}"]])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
x:xs -> (concat [prt 0 x , prt 0 xs])
|
||||||
|
|
||||||
|
instance Print PattAssign where
|
||||||
|
prt i e = case e of
|
||||||
|
PAss label patt -> prPrec i 0 (concat [prt 0 label , ["="] , prt 0 patt])
|
||||||
|
|
||||||
|
prtList es = case es of
|
||||||
|
[] -> (concat [])
|
||||||
|
[x] -> (concat [prt 0 x])
|
||||||
|
x:xs -> (concat [prt 0 x , [";"] , prt 0 xs])
|
||||||
|
|
||||||
|
|
||||||
116
src/GF/Canon/Share.hs
Normal file
116
src/GF/Canon/Share.hs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
module Share (shareModule, OptSpec, basicOpt, fullOpt) where
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import Ident
|
||||||
|
import GFC
|
||||||
|
import qualified CMacros as C
|
||||||
|
import Operations
|
||||||
|
import List
|
||||||
|
import qualified Modules as M
|
||||||
|
|
||||||
|
-- optimization: sharing branches in tables. AR 25/4/2003
|
||||||
|
-- following advice of Josef Svenningsson
|
||||||
|
|
||||||
|
type OptSpec = [Integer] ---
|
||||||
|
doOptFactor opt = elem 2 opt
|
||||||
|
basicOpt = []
|
||||||
|
fullOpt = [2]
|
||||||
|
|
||||||
|
shareModule :: OptSpec -> (Ident, CanonModInfo) -> (Ident, CanonModInfo)
|
||||||
|
shareModule opt (i,m) = case m of
|
||||||
|
M.ModMod (M.Module mt fs me ops js) ->
|
||||||
|
(i,M.ModMod (M.Module mt fs me ops (mapTree (shareInfo opt) js)))
|
||||||
|
_ -> (i,m)
|
||||||
|
|
||||||
|
shareInfo opt (c, CncCat ty t m) = (c, CncCat ty (shareOpt opt t) m)
|
||||||
|
shareInfo opt (c, CncFun k xs t m) = (c, CncFun k xs (shareOpt opt t) m)
|
||||||
|
shareInfo _ i = i
|
||||||
|
|
||||||
|
-- the function putting together optimizations
|
||||||
|
shareOpt :: OptSpec -> Term -> Term
|
||||||
|
shareOpt opt
|
||||||
|
| doOptFactor opt = share . factor 0
|
||||||
|
| otherwise = share
|
||||||
|
|
||||||
|
-- we need no counter to create new variable names, since variables are
|
||||||
|
-- local to tables
|
||||||
|
|
||||||
|
share :: Term -> Term
|
||||||
|
share t = case t of
|
||||||
|
T ty cs -> shareT ty [(p, share v) | Cas ps v <- cs, p <- ps] -- only substant.
|
||||||
|
R lts -> R [Ass l (share t) | Ass l t <- lts]
|
||||||
|
P t l -> P (share t) l
|
||||||
|
S t a -> S (share t) (share a)
|
||||||
|
C t a -> C (share t) (share a)
|
||||||
|
FV ts -> FV (map share ts)
|
||||||
|
|
||||||
|
_ -> t -- including D, which is always born shared
|
||||||
|
|
||||||
|
where
|
||||||
|
shareT ty = finalize ty . groupC . sortC
|
||||||
|
|
||||||
|
sortC :: [(Patt,Term)] -> [(Patt,Term)]
|
||||||
|
sortC = sortBy $ \a b -> compare (snd a) (snd b)
|
||||||
|
|
||||||
|
groupC :: [(Patt,Term)] -> [[(Patt,Term)]]
|
||||||
|
groupC = groupBy $ \a b -> snd a == snd b
|
||||||
|
|
||||||
|
finalize :: CType -> [[(Patt,Term)]] -> Term
|
||||||
|
finalize ty css = T ty [Cas (map fst ps) t | ps@((_,t):_) <- css]
|
||||||
|
|
||||||
|
|
||||||
|
-- do even more: factor parametric branches
|
||||||
|
|
||||||
|
factor :: Int -> Term -> Term
|
||||||
|
factor i t = case t of
|
||||||
|
T _ [_] -> t
|
||||||
|
T _ [] -> t
|
||||||
|
T ty cs -> T ty $ factors i [Cas [p] (factor (i+1) v) | Cas ps v <- cs, p <- ps]
|
||||||
|
R lts -> R [Ass l (factor i t) | Ass l t <- lts]
|
||||||
|
P t l -> P (factor i t) l
|
||||||
|
S t a -> S (factor i t) (factor i a)
|
||||||
|
C t a -> C (factor i t) (factor i a)
|
||||||
|
FV ts -> FV (map (factor i) ts)
|
||||||
|
|
||||||
|
_ -> t
|
||||||
|
where
|
||||||
|
|
||||||
|
factors i psvs = -- we know psvs has at least 2 elements
|
||||||
|
let p = pIdent i
|
||||||
|
vs' = map (mkFun p) psvs
|
||||||
|
in if allEqs vs'
|
||||||
|
then mkCase p vs'
|
||||||
|
else psvs
|
||||||
|
|
||||||
|
mkFun p (Cas [patt] val) = replace (C.patt2term patt) (LI p) val
|
||||||
|
|
||||||
|
allEqs (v:vs) = all (==v) vs
|
||||||
|
|
||||||
|
mkCase p (v:_) = [Cas [PV p] v]
|
||||||
|
|
||||||
|
pIdent i = identC ("p__" ++ show i)
|
||||||
|
|
||||||
|
|
||||||
|
-- we need to replace subterms
|
||||||
|
|
||||||
|
replace :: Term -> Term -> Term -> Term
|
||||||
|
replace old new trm = case trm of
|
||||||
|
T ty cs -> T ty [Cas p (repl v) | Cas p v <- cs]
|
||||||
|
P t l -> P (repl t) l
|
||||||
|
S t a -> S (repl t) (repl a)
|
||||||
|
C t a -> C (repl t) (repl a)
|
||||||
|
FV ts -> FV (map repl ts)
|
||||||
|
|
||||||
|
-- these are the important cases, since they can correspond to patterns
|
||||||
|
Con c ts | trm == old -> new
|
||||||
|
Con c ts -> Con c (map repl ts)
|
||||||
|
R _ | isRec && trm == old -> new
|
||||||
|
R lts -> R [Ass l (repl t) | Ass l t <- lts]
|
||||||
|
|
||||||
|
_ -> trm
|
||||||
|
where
|
||||||
|
repl = replace old new
|
||||||
|
isRec = case trm of
|
||||||
|
R _ -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
199
src/GF/Canon/SkelGFC.hs
Normal file
199
src/GF/Canon/SkelGFC.hs
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
module SkelGFC where
|
||||||
|
|
||||||
|
import Ident
|
||||||
|
|
||||||
|
-- Haskell module generated by the BNF converter
|
||||||
|
|
||||||
|
import AbsGFC
|
||||||
|
import ErrM
|
||||||
|
type Result = Err String
|
||||||
|
|
||||||
|
failure :: Show a => a -> Result
|
||||||
|
failure x = Bad $ "Undefined case: " ++ show x
|
||||||
|
|
||||||
|
transIdent :: Ident -> Result
|
||||||
|
transIdent x = case x of
|
||||||
|
_ -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transCanon :: Canon -> Result
|
||||||
|
transCanon x = case x of
|
||||||
|
Gr modules -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transModule :: Module -> Result
|
||||||
|
transModule x = case x of
|
||||||
|
Mod modtype extend open flags defs -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transModType :: ModType -> Result
|
||||||
|
transModType x = case x of
|
||||||
|
MTAbs id -> failure x
|
||||||
|
MTCnc id0 id -> failure x
|
||||||
|
MTRes id -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transExtend :: Extend -> Result
|
||||||
|
transExtend x = case x of
|
||||||
|
Ext id -> failure x
|
||||||
|
NoExt -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transOpen :: Open -> Result
|
||||||
|
transOpen x = case x of
|
||||||
|
NoOpens -> failure x
|
||||||
|
Opens ids -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transFlag :: Flag -> Result
|
||||||
|
transFlag x = case x of
|
||||||
|
Flg id0 id -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transDef :: Def -> Result
|
||||||
|
transDef x = case x of
|
||||||
|
AbsDCat id decls cidents -> failure x
|
||||||
|
AbsDFun id exp0 exp -> failure x
|
||||||
|
ResDPar id pardefs -> failure x
|
||||||
|
ResDOper id ctype term -> failure x
|
||||||
|
CncDCat id ctype term0 term -> failure x
|
||||||
|
CncDFun id cident argvars term0 term -> failure x
|
||||||
|
AnyDInd id0 status id -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transParDef :: ParDef -> Result
|
||||||
|
transParDef x = case x of
|
||||||
|
ParD id ctypes -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transStatus :: Status -> Result
|
||||||
|
transStatus x = case x of
|
||||||
|
Canon -> failure x
|
||||||
|
NonCan -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transCIdent :: CIdent -> Result
|
||||||
|
transCIdent x = case x of
|
||||||
|
CIQ id0 id -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transExp :: Exp -> Result
|
||||||
|
transExp x = case x of
|
||||||
|
EApp exp0 exp -> failure x
|
||||||
|
EProd id exp0 exp -> failure x
|
||||||
|
EAbs id exp -> failure x
|
||||||
|
EAtom atom -> failure x
|
||||||
|
EEq equations -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transSort :: Sort -> Result
|
||||||
|
transSort x = case x of
|
||||||
|
SType -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transEquation :: Equation -> Result
|
||||||
|
transEquation x = case x of
|
||||||
|
Equ apatts exp -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transAPatt :: APatt -> Result
|
||||||
|
transAPatt x = case x of
|
||||||
|
APC cident apatts -> failure x
|
||||||
|
APV id -> failure x
|
||||||
|
APS str -> failure x
|
||||||
|
API n -> failure x
|
||||||
|
APW -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transAtom :: Atom -> Result
|
||||||
|
transAtom x = case x of
|
||||||
|
AC cident -> failure x
|
||||||
|
AD cident -> failure x
|
||||||
|
AV id -> failure x
|
||||||
|
AM n -> failure x
|
||||||
|
AS str -> failure x
|
||||||
|
AI n -> failure x
|
||||||
|
AT sort -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transDecl :: Decl -> Result
|
||||||
|
transDecl x = case x of
|
||||||
|
Decl id exp -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transCType :: CType -> Result
|
||||||
|
transCType x = case x of
|
||||||
|
RecType labellings -> failure x
|
||||||
|
Table ctype0 ctype -> failure x
|
||||||
|
Cn cident -> failure x
|
||||||
|
TStr -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transLabelling :: Labelling -> Result
|
||||||
|
transLabelling x = case x of
|
||||||
|
Lbg label ctype -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transTerm :: Term -> Result
|
||||||
|
transTerm x = case x of
|
||||||
|
Arg argvar -> failure x
|
||||||
|
I cident -> failure x
|
||||||
|
Con cident terms -> failure x
|
||||||
|
LI id -> failure x
|
||||||
|
R assigns -> failure x
|
||||||
|
P term label -> failure x
|
||||||
|
T ctype cases -> failure x
|
||||||
|
S term0 term -> failure x
|
||||||
|
C term0 term -> failure x
|
||||||
|
FV terms -> failure x
|
||||||
|
K tokn -> failure x
|
||||||
|
E -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transTokn :: Tokn -> Result
|
||||||
|
transTokn x = case x of
|
||||||
|
KS str -> failure x
|
||||||
|
KP strs variants -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transAssign :: Assign -> Result
|
||||||
|
transAssign x = case x of
|
||||||
|
Ass label term -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transCase :: Case -> Result
|
||||||
|
transCase x = case x of
|
||||||
|
Cas patts term -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transVariant :: Variant -> Result
|
||||||
|
transVariant x = case x of
|
||||||
|
Var strs0 strs -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transLabel :: Label -> Result
|
||||||
|
transLabel x = case x of
|
||||||
|
L id -> failure x
|
||||||
|
LV n -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transArgVar :: ArgVar -> Result
|
||||||
|
transArgVar x = case x of
|
||||||
|
A id n -> failure x
|
||||||
|
AB id n0 n -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transPatt :: Patt -> Result
|
||||||
|
transPatt x = case x of
|
||||||
|
PC cident patts -> failure x
|
||||||
|
PV id -> failure x
|
||||||
|
PW -> failure x
|
||||||
|
PR pattassigns -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
transPattAssign :: PattAssign -> Result
|
||||||
|
transPattAssign x = case x of
|
||||||
|
PAss label patt -> failure x
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
25
src/GF/Canon/TestGFC.hs
Normal file
25
src/GF/Canon/TestGFC.hs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- automatically generated by BNF Converter
|
||||||
|
module TestGFC where
|
||||||
|
|
||||||
|
import LexGFC
|
||||||
|
import ParGFC
|
||||||
|
import SkelGFC
|
||||||
|
import PrintGFC
|
||||||
|
import AbsGFC
|
||||||
|
|
||||||
|
import ErrM
|
||||||
|
|
||||||
|
type ParseFun a = [Token] -> Err a
|
||||||
|
|
||||||
|
myLLexer = myLexer
|
||||||
|
|
||||||
|
runFile :: (Print a, Show a) => ParseFun a -> FilePath -> IO()
|
||||||
|
runFile p f = readFile f >>= run p
|
||||||
|
|
||||||
|
run :: (Print a, Show a) => ParseFun a -> String -> IO()
|
||||||
|
run p s = case (p (myLLexer s)) of
|
||||||
|
Bad s -> do putStrLn "\nParse Failed...\n"
|
||||||
|
putStrLn s
|
||||||
|
Ok tree -> do putStrLn "\nParse Successful!"
|
||||||
|
putStrLn $ "\n[Abstract Syntax]\n\n" ++ show tree
|
||||||
|
putStrLn $ "\n[Linearized tree]\n\n" ++ printTree tree
|
||||||
37
src/GF/Canon/Unlex.hs
Normal file
37
src/GF/Canon/Unlex.hs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
module Unlex where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Str
|
||||||
|
|
||||||
|
import Char
|
||||||
|
import List (isPrefixOf)
|
||||||
|
|
||||||
|
-- elementary text postprocessing. AR 21/11/2001
|
||||||
|
|
||||||
|
formatAsText :: String -> String
|
||||||
|
formatAsText = unwords . format . cap . words where
|
||||||
|
format ws = case ws of
|
||||||
|
w : c : ww | major c -> (w ++ c) : format (cap ww)
|
||||||
|
w : c : ww | minor c -> (w ++ c) : format ww
|
||||||
|
c : ww | para c -> "\n\n" : format ww
|
||||||
|
w : ww -> w : format ww
|
||||||
|
[] -> []
|
||||||
|
cap (p:(c:cs):ww) | para p = p : (toUpper c : cs) : ww
|
||||||
|
cap ((c:cs):ww) = (toUpper c : cs) : ww
|
||||||
|
cap [] = []
|
||||||
|
major = flip elem (map (:[]) ".!?")
|
||||||
|
minor = flip elem (map (:[]) ",:;")
|
||||||
|
para = (=="<p>")
|
||||||
|
|
||||||
|
unlex :: [Str] -> String
|
||||||
|
unlex = formatAsText . performBinds . concat . map sstr . take 1 ----
|
||||||
|
|
||||||
|
-- modified from GF/src/Text by adding hyphen
|
||||||
|
performBinds :: String -> String
|
||||||
|
performBinds = unwords . format . words where
|
||||||
|
format ws = case ws of
|
||||||
|
w : "-" : u : ws -> format ((w ++ "-" ++ u) : ws)
|
||||||
|
w : "&+" : u : ws -> format ((w ++ u) : ws)
|
||||||
|
w : ws -> w : format ws
|
||||||
|
[] -> []
|
||||||
|
|
||||||
665
src/GF/Compile/CheckGrammar.hs
Normal file
665
src/GF/Compile/CheckGrammar.hs
Normal file
@@ -0,0 +1,665 @@
|
|||||||
|
module CheckGrammar where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Modules
|
||||||
|
import Refresh ----
|
||||||
|
|
||||||
|
import TypeCheck
|
||||||
|
|
||||||
|
import PrGrammar
|
||||||
|
import Lookup
|
||||||
|
import LookAbs
|
||||||
|
import Macros
|
||||||
|
import ReservedWords ----
|
||||||
|
import PatternMatch
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import CheckM
|
||||||
|
|
||||||
|
import List
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- AR 4/12/1999 -- 1/4/2000 -- 8/9/2001 -- 15/5/2002 -- 27/11/2002 -- 18/6/2003
|
||||||
|
|
||||||
|
-- type checking also does the following modifications:
|
||||||
|
-- * types of operations and local constants are inferred and put in place
|
||||||
|
-- * both these types and linearization types are computed
|
||||||
|
-- * tables are type-annotated
|
||||||
|
|
||||||
|
showCheckModule :: [SourceModule] -> SourceModule -> Err ([SourceModule],String)
|
||||||
|
showCheckModule mos m = do
|
||||||
|
(st,(_,msg)) <- checkStart $ checkModule mos m
|
||||||
|
return (st, unlines $ reverse msg)
|
||||||
|
|
||||||
|
-- checking is performed in dependency order of modules
|
||||||
|
|
||||||
|
checkModule :: [SourceModule] -> SourceModule -> Check [SourceModule]
|
||||||
|
checkModule ms (name,mod) = checkIn ("checking module" +++ prt name) $ case mod of
|
||||||
|
|
||||||
|
ModMod mo@(Module mt fs me ops js) -> case mt of
|
||||||
|
MTAbstract -> do
|
||||||
|
js' <- mapMTree (checkAbsInfo gr name) js
|
||||||
|
return $ (name, ModMod (Module mt fs me ops js')) : ms
|
||||||
|
|
||||||
|
MTResource -> do
|
||||||
|
js' <- mapMTree (checkResInfo gr) js
|
||||||
|
return $ (name, ModMod (Module mt fs me ops js')) : ms
|
||||||
|
|
||||||
|
MTConcrete a -> do
|
||||||
|
ModMod abs <- checkErr $ lookupModule gr a
|
||||||
|
checkCompleteGrammar abs mo
|
||||||
|
js' <- mapMTree (checkCncInfo gr name (a,abs)) js
|
||||||
|
return $ (name, ModMod (Module mt fs me ops js')) : ms
|
||||||
|
_ -> return $ (name,mod) : ms
|
||||||
|
where
|
||||||
|
gr = MGrammar $ (name,mod):ms
|
||||||
|
|
||||||
|
checkAbsInfo :: SourceGrammar -> Ident -> (Ident,Info) -> Check (Ident,Info)
|
||||||
|
checkAbsInfo st m (c,info) = do
|
||||||
|
---- checkReservedId c
|
||||||
|
case info of
|
||||||
|
AbsCat (Yes cont) _ -> mkCheck "category" $
|
||||||
|
checkContext st cont ---- also cstrs
|
||||||
|
AbsFun (Yes typ) (Yes d) -> mkCheck "function" $
|
||||||
|
checkTyp st typ ----- ++
|
||||||
|
----- checkEquation st (m,c) d ---- also if there's no def!
|
||||||
|
_ -> return (c,info)
|
||||||
|
where
|
||||||
|
mkCheck cat ss = case ss of
|
||||||
|
[] -> return (c,info)
|
||||||
|
["[]"] -> return (c,info) ----
|
||||||
|
_ -> checkErr $ prtBad (unlines ss ++++ "in" +++ cat) c
|
||||||
|
|
||||||
|
checkCompleteGrammar :: SourceAbs -> SourceCnc -> Check ()
|
||||||
|
checkCompleteGrammar abs cnc = mapM_ checkWarn $
|
||||||
|
checkComplete [f | (f, AbsFun (Yes _) _) <- abs'] cnc'
|
||||||
|
where
|
||||||
|
abs' = tree2list $ jments abs
|
||||||
|
cnc' = mapTree fst $ jments cnc
|
||||||
|
checkComplete sought given = foldr ckOne [] sought
|
||||||
|
where
|
||||||
|
ckOne f = if isInBinTree f given
|
||||||
|
then id
|
||||||
|
else (("Warning: no linearization of" +++ prt f):)
|
||||||
|
|
||||||
|
-- General Principle: only Yes-values are checked.
|
||||||
|
-- A May-value has always been checked in its origin module.
|
||||||
|
|
||||||
|
checkResInfo :: SourceGrammar -> (Ident,Info) -> Check (Ident,Info)
|
||||||
|
checkResInfo gr (c,info) = do
|
||||||
|
checkReservedId c
|
||||||
|
case info of
|
||||||
|
|
||||||
|
ResOper pty pde -> chIn "operation" $ do
|
||||||
|
(pty', pde') <- case (pty,pde) of
|
||||||
|
(Yes ty, Yes de) -> do
|
||||||
|
ty' <- check ty typeType >>= comp . fst
|
||||||
|
(de',_) <- check de ty'
|
||||||
|
return (Yes ty', Yes de')
|
||||||
|
(Nope, Yes de) -> do
|
||||||
|
(de',ty') <- infer de
|
||||||
|
return (Yes ty', Yes de')
|
||||||
|
_ -> return (pty, pde) --- other cases are uninteresting
|
||||||
|
return (c, ResOper pty' pde')
|
||||||
|
|
||||||
|
ResParam (Yes pcs) -> chIn "parameter type" $ do
|
||||||
|
mapM_ ((mapM_ (checkIfParType gr . snd)) . snd) pcs
|
||||||
|
return (c,info)
|
||||||
|
|
||||||
|
_ -> return (c,info)
|
||||||
|
where
|
||||||
|
infer = inferLType gr
|
||||||
|
check = checkLType gr
|
||||||
|
chIn cat = checkIn ("Happened in" +++ cat +++ prt c +++ ":")
|
||||||
|
comp = computeLType gr
|
||||||
|
|
||||||
|
checkCncInfo :: SourceGrammar -> Ident -> (Ident,SourceAbs) ->
|
||||||
|
(Ident,Info) -> Check (Ident,Info)
|
||||||
|
checkCncInfo gr m (a,abs) (c,info) = do
|
||||||
|
checkReservedId c
|
||||||
|
case info of
|
||||||
|
|
||||||
|
CncFun _ (Yes trm) mpr -> chIn "linearization of" $ do
|
||||||
|
typ <- checkErr $ lookupFunTypeSrc gr a c
|
||||||
|
cat0 <- checkErr $ valCat typ
|
||||||
|
(cont,val) <- linTypeOfType gr m typ -- creates arg vars
|
||||||
|
(trm',_) <- check trm (mkFunType (map snd cont) val) -- erases arg vars
|
||||||
|
checkPrintname gr mpr
|
||||||
|
cat <- return $ snd cat0
|
||||||
|
return (c, CncFun (Just (cat,(cont,val))) (Yes trm') mpr)
|
||||||
|
-- cat for cf, typ for pe
|
||||||
|
|
||||||
|
CncCat (Yes typ) mdef mpr -> chIn "linearization type of" $ do
|
||||||
|
typ' <- checkIfLinType gr typ
|
||||||
|
mdef' <- case mdef of
|
||||||
|
Yes def -> do
|
||||||
|
(def',_) <- checkLType gr def (mkFunType [typeStr] typ)
|
||||||
|
return $ Yes def'
|
||||||
|
_ -> return mdef
|
||||||
|
checkPrintname gr mpr
|
||||||
|
return (c,CncCat (Yes typ') mdef' mpr)
|
||||||
|
|
||||||
|
_ -> return (c,info)
|
||||||
|
|
||||||
|
where
|
||||||
|
env = gr
|
||||||
|
infer = inferLType gr
|
||||||
|
comp = computeLType gr
|
||||||
|
check = checkLType gr
|
||||||
|
chIn cat = checkIn ("Happened in" +++ cat +++ prt c +++ ":")
|
||||||
|
|
||||||
|
checkIfParType :: SourceGrammar -> Type -> Check ()
|
||||||
|
checkIfParType st typ = checkCond ("Not parameter type" +++ prt typ) (isParType typ)
|
||||||
|
where
|
||||||
|
isParType ty = True ----
|
||||||
|
{- case ty of
|
||||||
|
Cn typ -> case lookupConcrete st typ of
|
||||||
|
Ok (CncParType _ _ _) -> True
|
||||||
|
Ok (CncOper _ ty' _) -> isParType ty'
|
||||||
|
_ -> False
|
||||||
|
Q p t -> case lookupInPackage st (p,t) of
|
||||||
|
Ok (CncParType _ _ _) -> True
|
||||||
|
_ -> False
|
||||||
|
RecType r -> all (isParType . snd) r
|
||||||
|
_ -> False
|
||||||
|
-}
|
||||||
|
|
||||||
|
checkIfStrType :: SourceGrammar -> Type -> Check ()
|
||||||
|
checkIfStrType st typ = case typ of
|
||||||
|
Table arg val -> do
|
||||||
|
checkIfParType st arg
|
||||||
|
checkIfStrType st val
|
||||||
|
_ | typ == typeStr -> return ()
|
||||||
|
_ -> prtFail "not a string type" typ
|
||||||
|
|
||||||
|
|
||||||
|
checkIfLinType :: SourceGrammar -> Type -> Check Type
|
||||||
|
checkIfLinType st typ0 = do
|
||||||
|
typ <- computeLType st typ0
|
||||||
|
case typ of
|
||||||
|
RecType r -> do
|
||||||
|
let (lins,ihs) = partition (isLinLabel .fst) r
|
||||||
|
--- checkErr $ checkUnique $ map fst r
|
||||||
|
mapM_ checkInh ihs
|
||||||
|
mapM_ checkLin lins
|
||||||
|
_ -> prtFail "a linearization type must be a record type instead of" typ
|
||||||
|
return typ
|
||||||
|
|
||||||
|
where
|
||||||
|
checkInh (label,typ) = checkIfParType st typ
|
||||||
|
checkLin (label,typ) = checkIfStrType st typ
|
||||||
|
|
||||||
|
|
||||||
|
computeLType :: SourceGrammar -> Type -> Check Type
|
||||||
|
computeLType gr t = do
|
||||||
|
g0 <- checkGetContext
|
||||||
|
let g = [(x, Vr x) | (x,_) <- g0]
|
||||||
|
checkInContext g $ comp t
|
||||||
|
where
|
||||||
|
comp ty = case ty of
|
||||||
|
|
||||||
|
Q m ident -> do
|
||||||
|
ty' <- checkErr (lookupResDef gr m ident)
|
||||||
|
if ty' == ty then return ty else comp ty' --- is this necessary to test?
|
||||||
|
|
||||||
|
Vr ident -> checkLookup ident -- never needed to compute!
|
||||||
|
|
||||||
|
App f a -> do
|
||||||
|
f' <- comp f
|
||||||
|
a' <- comp a
|
||||||
|
case f' of
|
||||||
|
Abs x b -> checkInContext [(x,a')] $ comp b
|
||||||
|
_ -> return $ App f' a'
|
||||||
|
|
||||||
|
Prod x a b -> do
|
||||||
|
a' <- comp a
|
||||||
|
b' <- checkInContext [(x,Vr x)] $ comp b
|
||||||
|
return $ Prod x a' b'
|
||||||
|
|
||||||
|
Abs x b -> do
|
||||||
|
b' <- checkInContext [(x,Vr x)] $ comp b
|
||||||
|
return $ Abs x b'
|
||||||
|
|
||||||
|
ExtR r s -> do
|
||||||
|
r' <- comp r
|
||||||
|
s' <- comp s
|
||||||
|
case (r',s') of
|
||||||
|
(RecType rs, RecType ss) -> return $ RecType (rs ++ ss)
|
||||||
|
_ -> return $ ExtR r' s'
|
||||||
|
|
||||||
|
_ | isPredefConstant ty -> return ty
|
||||||
|
|
||||||
|
_ -> composOp comp ty
|
||||||
|
|
||||||
|
checkPrintname :: SourceGrammar -> Perh Term -> Check ()
|
||||||
|
checkPrintname st (Yes t) = checkLType st t typeStr >> return ()
|
||||||
|
checkPrintname _ _ = return ()
|
||||||
|
|
||||||
|
-- for grammars obtained otherwise than by parsing ---- update!!
|
||||||
|
checkReservedId :: Ident -> Check ()
|
||||||
|
checkReservedId x = let c = prt x in
|
||||||
|
if isResWord c
|
||||||
|
then checkWarn ("Warning: reserved word used as identifier:" +++ c)
|
||||||
|
else return ()
|
||||||
|
|
||||||
|
-- the underlying algorithms
|
||||||
|
|
||||||
|
inferLType :: SourceGrammar -> Term -> Check (Term, Type)
|
||||||
|
inferLType gr trm = case trm of
|
||||||
|
|
||||||
|
Q m ident -> checks [
|
||||||
|
termWith trm $ checkErr (lookupResType gr m ident)
|
||||||
|
,
|
||||||
|
checkErr (lookupResDef gr m ident) >>= infer
|
||||||
|
,
|
||||||
|
prtFail "cannot infer type of constant" trm
|
||||||
|
]
|
||||||
|
|
||||||
|
QC m ident -> checks [
|
||||||
|
termWith trm $ checkErr (lookupResType gr m ident)
|
||||||
|
,
|
||||||
|
checkErr (lookupResDef gr m ident) >>= infer
|
||||||
|
,
|
||||||
|
prtFail "cannot infer type of canonical constant" trm
|
||||||
|
]
|
||||||
|
|
||||||
|
Vr ident -> termWith trm $ checkLookup ident
|
||||||
|
|
||||||
|
App f a -> do
|
||||||
|
(f',fty) <- infer f
|
||||||
|
fty' <- comp fty
|
||||||
|
case fty' of
|
||||||
|
Prod z arg val -> do
|
||||||
|
a' <- justCheck a arg
|
||||||
|
ty <- if isWildIdent z
|
||||||
|
then return val
|
||||||
|
else substituteLType [(z,a')] val
|
||||||
|
return (App f' a',ty)
|
||||||
|
_ -> prtFail ("function type expected for" +++ prt f +++ "instead of") fty
|
||||||
|
|
||||||
|
S f x -> do
|
||||||
|
(f', fty) <- infer f
|
||||||
|
case fty of
|
||||||
|
Table arg val -> do
|
||||||
|
x'<- justCheck x arg
|
||||||
|
return (S f' x', val)
|
||||||
|
_ -> prtFail "table lintype expected for the table in" trm
|
||||||
|
|
||||||
|
P t i -> do
|
||||||
|
(t',ty) <- infer t --- ??
|
||||||
|
ty' <- comp ty
|
||||||
|
termWith (P t' i) $ checkErr $ case ty' of
|
||||||
|
RecType ts -> maybeErr ("unknown label" +++ show i +++ "in" +++ show ty') $
|
||||||
|
lookup i ts
|
||||||
|
_ -> prtBad ("record type expected for" +++ prt t +++ "instead of") ty'
|
||||||
|
|
||||||
|
R r -> do
|
||||||
|
let (ls,fs) = unzip r
|
||||||
|
fsts <- mapM inferM fs
|
||||||
|
let ts = [ty | (Just ty,_) <- fsts]
|
||||||
|
checkCond ("cannot infer type of record"+++ prt trm) (length ts == length fsts)
|
||||||
|
return $ (R (zip ls fsts), RecType (zip ls ts))
|
||||||
|
|
||||||
|
T (TTyped arg) pts -> do
|
||||||
|
(_,val) <- checks $ map (inferCase (Just arg)) pts
|
||||||
|
check trm (Table arg val)
|
||||||
|
T (TComp arg) pts -> do
|
||||||
|
(_,val) <- checks $ map (inferCase (Just arg)) pts
|
||||||
|
check trm (Table arg val)
|
||||||
|
T ti pts -> do -- tries to guess: good in oper type inference
|
||||||
|
let pts' = [pt | pt@(p,_) <- pts, isConstPatt p]
|
||||||
|
if null pts'
|
||||||
|
then prtFail "cannot infer table type of" trm
|
||||||
|
else do
|
||||||
|
(arg,val) <- checks $ map (inferCase Nothing) pts'
|
||||||
|
check trm (Table arg val)
|
||||||
|
|
||||||
|
K s -> do
|
||||||
|
if elem ' ' s
|
||||||
|
then checkWarn ("Warning: space in token \"" ++ s ++
|
||||||
|
"\". Lexical analysis may fail.")
|
||||||
|
else return ()
|
||||||
|
return (trm, typeTok)
|
||||||
|
|
||||||
|
EInt i -> return (trm, typeInt)
|
||||||
|
|
||||||
|
Empty -> return (trm, typeTok)
|
||||||
|
|
||||||
|
C s1 s2 ->
|
||||||
|
check2 (flip justCheck typeStr) C s1 s2 typeStr
|
||||||
|
|
||||||
|
Glue s1 s2 ->
|
||||||
|
check2 (flip justCheck typeStr) Glue s1 s2 typeStr ---- typeTok
|
||||||
|
|
||||||
|
Strs ts -> do
|
||||||
|
ts' <- mapM (\t -> justCheck t typeStr) ts
|
||||||
|
return (Strs ts', typeStrs)
|
||||||
|
|
||||||
|
Alts (t,aa) -> do
|
||||||
|
t' <- justCheck t typeStr
|
||||||
|
aa' <- flip mapM aa (\ (c,v) -> do
|
||||||
|
c' <- justCheck c typeStr
|
||||||
|
v' <- justCheck v typeStrs
|
||||||
|
return (c',v'))
|
||||||
|
return (Alts (t',aa'), typeStr)
|
||||||
|
|
||||||
|
RecType r -> do
|
||||||
|
let (ls,ts) = unzip r
|
||||||
|
ts' <- mapM (flip justCheck typeType) ts
|
||||||
|
return (RecType (zip ls ts'), typeType)
|
||||||
|
|
||||||
|
ExtR r s -> do
|
||||||
|
(r',rT) <- infer r
|
||||||
|
rT' <- comp rT
|
||||||
|
(s',sT) <- infer s
|
||||||
|
sT' <- comp sT
|
||||||
|
let trm' = ExtR r' s'
|
||||||
|
case (rT', sT') of
|
||||||
|
(RecType rs, RecType ss) -> return (trm', RecType (rs ++ ss))
|
||||||
|
_ | rT' == typeType && sT' == typeType -> return (trm', typeType)
|
||||||
|
_ -> prtFail "records or record types expected in" trm
|
||||||
|
|
||||||
|
Sort _ ->
|
||||||
|
termWith trm $ return typeType
|
||||||
|
|
||||||
|
Prod x a b -> do
|
||||||
|
a' <- justCheck a typeType
|
||||||
|
b' <- checkInContext [(x,a')] $ justCheck b typeType
|
||||||
|
return (Prod x a' b', typeType)
|
||||||
|
|
||||||
|
Table p t -> do
|
||||||
|
p' <- justCheck p typeType --- check p partype!
|
||||||
|
t' <- justCheck t typeType
|
||||||
|
return $ (Table p' t', typeType)
|
||||||
|
|
||||||
|
FV vs -> do
|
||||||
|
(ty,_) <- checks $ map infer vs
|
||||||
|
--- checkIfComplexVariantType trm ty
|
||||||
|
check trm ty
|
||||||
|
|
||||||
|
_ -> prtFail "cannot infer lintype of" trm
|
||||||
|
|
||||||
|
where
|
||||||
|
env = gr
|
||||||
|
infer = inferLType env
|
||||||
|
comp = computeLType env
|
||||||
|
|
||||||
|
check = checkLType env
|
||||||
|
|
||||||
|
justCheck ty te = check ty te >>= return . fst
|
||||||
|
|
||||||
|
-- for record fields, which may be typed
|
||||||
|
inferM (mty, t) = do
|
||||||
|
(t', ty') <- case mty of
|
||||||
|
Just ty -> check ty t
|
||||||
|
_ -> infer t
|
||||||
|
return (Just ty',t')
|
||||||
|
|
||||||
|
inferCase mty (patt,term) = do
|
||||||
|
arg <- maybe (inferPatt patt) return mty
|
||||||
|
cont <- pattContext env arg patt
|
||||||
|
i <- checkUpdates cont
|
||||||
|
(_,val) <- infer term
|
||||||
|
checkResets i
|
||||||
|
return (arg,val)
|
||||||
|
isConstPatt p = case p of
|
||||||
|
PC _ ps -> True --- all isConstPatt ps
|
||||||
|
PP _ _ ps -> True --- all isConstPatt ps
|
||||||
|
PR ps -> all (isConstPatt . snd) ps
|
||||||
|
PT _ p -> isConstPatt p
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
inferPatt p = case p of
|
||||||
|
PP q c ps -> checkErr $ lookupResType gr q c >>= valTypeCnc
|
||||||
|
_ -> infer (patt2term p) >>= return . snd
|
||||||
|
|
||||||
|
checkLType :: SourceGrammar -> Term -> Type -> Check (Term, Type)
|
||||||
|
checkLType env trm typ0 = do
|
||||||
|
|
||||||
|
typ <- comp typ0
|
||||||
|
|
||||||
|
case trm of
|
||||||
|
|
||||||
|
Abs x c -> do
|
||||||
|
case typ of
|
||||||
|
Prod z a b -> do
|
||||||
|
checkUpdate (x,a)
|
||||||
|
(c',b') <- if isWildIdent z
|
||||||
|
then check c b
|
||||||
|
else do
|
||||||
|
b' <- checkIn "abs" $ substituteLType [(z,Vr x)] b
|
||||||
|
check c b'
|
||||||
|
checkReset
|
||||||
|
return $ (Abs x c', Prod x a b')
|
||||||
|
_ -> prtFail "product expected instead of" typ
|
||||||
|
|
||||||
|
T _ [] ->
|
||||||
|
prtFail "found empty table in type" typ
|
||||||
|
T _ cs -> case typ of
|
||||||
|
Table arg val -> do
|
||||||
|
case allParamValues env arg of
|
||||||
|
Ok vs -> do
|
||||||
|
let ps0 = map fst cs
|
||||||
|
ps <- checkErr $ testOvershadow ps0 vs
|
||||||
|
if null ps
|
||||||
|
then return ()
|
||||||
|
else checkWarn $ "Warning: patterns never reached:" +++
|
||||||
|
concat (intersperse ", " (map prt ps))
|
||||||
|
|
||||||
|
_ -> return () -- happens with variable types
|
||||||
|
cs' <- mapM (checkCase arg val) cs
|
||||||
|
return (T (TTyped arg) cs', typ)
|
||||||
|
_ -> prtFail "table type expected for table instead of" typ
|
||||||
|
|
||||||
|
R r -> case typ of --- why needed? because inference may be too difficult
|
||||||
|
RecType rr -> do
|
||||||
|
let (ls,_) = unzip rr -- labels of expected type
|
||||||
|
fsts <- mapM (checkM r) rr -- check that they are found in the record
|
||||||
|
return $ (R fsts, typ) -- normalize record
|
||||||
|
|
||||||
|
_ -> prtFail "record type expected in type checking instead of" typ
|
||||||
|
|
||||||
|
ExtR r s -> case typ of
|
||||||
|
_ | typ == typeType -> do
|
||||||
|
trm' <- comp trm
|
||||||
|
case trm' of
|
||||||
|
RecType _ -> termWith trm $ return typeType
|
||||||
|
_ -> prtFail "invalid record type extension" trm
|
||||||
|
RecType rr -> checks [
|
||||||
|
do (r',ty) <- infer r
|
||||||
|
case ty of
|
||||||
|
RecType rr1 -> do
|
||||||
|
s' <- justCheck s (minusRecType rr rr1)
|
||||||
|
return $ (ExtR r' s', typ)
|
||||||
|
_ -> prtFail "record type expected in extension of" r
|
||||||
|
,
|
||||||
|
do (s',ty) <- infer s
|
||||||
|
case ty of
|
||||||
|
RecType rr2 -> do
|
||||||
|
r' <- justCheck r (minusRecType rr rr2)
|
||||||
|
return $ (ExtR r' s', typ)
|
||||||
|
_ -> prtFail "record type expected in extension with" s
|
||||||
|
]
|
||||||
|
_ -> prtFail "record extension not meaningful for" typ
|
||||||
|
|
||||||
|
FV vs -> do
|
||||||
|
ttys <- mapM (flip check typ) vs
|
||||||
|
--- checkIfComplexVariantType trm typ
|
||||||
|
return (FV (map fst ttys), typ) --- typ' ?
|
||||||
|
|
||||||
|
S tab arg -> do
|
||||||
|
(tab',ty) <- infer tab
|
||||||
|
ty' <- comp ty
|
||||||
|
case ty' of
|
||||||
|
Table p t -> do
|
||||||
|
(arg',val) <- check arg p
|
||||||
|
checkEq typ t trm
|
||||||
|
return (S tab' arg', t)
|
||||||
|
_ -> prtFail "table type expected for applied table instead of" ty'
|
||||||
|
|
||||||
|
Let (x,(mty,def)) body -> case mty of
|
||||||
|
Just ty -> do
|
||||||
|
(def',ty') <- check def ty
|
||||||
|
checkUpdate (x,ty')
|
||||||
|
body' <- justCheck body typ
|
||||||
|
checkReset
|
||||||
|
return (Let (x,(Just ty',def')) body', typ)
|
||||||
|
_ -> do
|
||||||
|
(def',ty) <- infer def -- tries to infer type of local constant
|
||||||
|
check (Let (x,(Just ty,def')) body) typ
|
||||||
|
|
||||||
|
_ -> do
|
||||||
|
(trm',ty') <- infer trm
|
||||||
|
termWith trm' $ checkEq typ ty' trm'
|
||||||
|
where
|
||||||
|
cnc = env
|
||||||
|
infer = inferLType env
|
||||||
|
comp = computeLType env
|
||||||
|
|
||||||
|
check = checkLType env
|
||||||
|
|
||||||
|
justCheck ty te = check ty te >>= return . fst
|
||||||
|
|
||||||
|
checkEq = checkEqLType env
|
||||||
|
|
||||||
|
minusRecType rr rr1 = RecType [(l,v) | (l,v) <- rr, notElem l (map fst rr1)]
|
||||||
|
|
||||||
|
checkM rms (l,ty) = case lookup l rms of
|
||||||
|
Just (Just ty0,t) -> do
|
||||||
|
checkEq ty ty0 t
|
||||||
|
(t',ty') <- check t ty
|
||||||
|
return (l,(Just ty',t'))
|
||||||
|
Just (_,t) -> do
|
||||||
|
(t',ty') <- check t ty
|
||||||
|
return (l,(Just ty',t'))
|
||||||
|
_ -> prtFail "cannot find value for label" l
|
||||||
|
|
||||||
|
checkCase arg val (p,t) = do
|
||||||
|
cont <- pattContext env arg p
|
||||||
|
i <- checkUpdates cont
|
||||||
|
t' <- justCheck t val
|
||||||
|
checkResets i
|
||||||
|
return (p,t')
|
||||||
|
|
||||||
|
pattContext :: LTEnv -> Type -> Patt -> Check Context
|
||||||
|
pattContext env typ p = case p of
|
||||||
|
PV x -> return [(x,typ)]
|
||||||
|
PP q c ps -> do
|
||||||
|
t <- checkErr $ lookupResType cnc q c
|
||||||
|
(cont,v) <- checkErr $ typeFormCnc t
|
||||||
|
checkCond ("wrong number of arguments for constructor in" +++ prt p)
|
||||||
|
(length cont == length ps)
|
||||||
|
checkEqLType env typ v (patt2term p)
|
||||||
|
mapM (uncurry (pattContext env)) (zip (map snd cont) ps) >>= return . concat
|
||||||
|
PR r -> do
|
||||||
|
typ' <- computeLType env typ
|
||||||
|
case typ' of
|
||||||
|
RecType t -> do
|
||||||
|
let pts = [(ty,tr) | (l,tr) <- r, Just ty <- [lookup l t]]
|
||||||
|
mapM (uncurry (pattContext env)) pts >>= return . concat
|
||||||
|
_ -> prtFail "record type expected for pattern instead of" typ'
|
||||||
|
PT t p' -> do
|
||||||
|
checkEqLType env typ t (patt2term p')
|
||||||
|
pattContext env typ p'
|
||||||
|
|
||||||
|
_ -> return [] ----
|
||||||
|
where
|
||||||
|
cnc = env
|
||||||
|
|
||||||
|
-- auxiliaries
|
||||||
|
|
||||||
|
type LTEnv = SourceGrammar
|
||||||
|
|
||||||
|
termWith :: Term -> Check Type -> Check (Term, Type)
|
||||||
|
termWith t ct = do
|
||||||
|
ty <- ct
|
||||||
|
return (t,ty)
|
||||||
|
|
||||||
|
-- light-weight substitution for dep. types
|
||||||
|
substituteLType :: Context -> Type -> Check Type
|
||||||
|
substituteLType g t = case t of
|
||||||
|
Vr x -> return $ maybe t id $ lookup x g
|
||||||
|
_ -> composOp (substituteLType g) t
|
||||||
|
|
||||||
|
-- compositional check/infer of binary operations
|
||||||
|
check2 :: (Term -> Check Term) -> (Term -> Term -> Term) ->
|
||||||
|
Term -> Term -> Type -> Check (Term,Type)
|
||||||
|
check2 chk con a b t = do
|
||||||
|
a' <- chk a
|
||||||
|
b' <- chk b
|
||||||
|
return (con a' b', t)
|
||||||
|
|
||||||
|
checkEqLType :: LTEnv -> Type -> Type -> Term -> Check Type
|
||||||
|
checkEqLType env t u trm = do
|
||||||
|
t' <- comp t
|
||||||
|
u' <- comp u
|
||||||
|
if alpha [] t' u'
|
||||||
|
then return t'
|
||||||
|
else raise ("type of" +++ prt trm +++
|
||||||
|
": expected" +++ prt t' ++ ", inferred" +++ prt u')
|
||||||
|
where
|
||||||
|
alpha g t u = case (t,u) of --- quick hack version of TC.eqVal
|
||||||
|
(Prod x a b, Prod y c d) -> alpha g a c && alpha ((x,y):g) b d
|
||||||
|
|
||||||
|
---- this should be made in Rename
|
||||||
|
(Q m a, Q n b) | a == b -> elem m (allExtends env n)
|
||||||
|
|| elem n (allExtends env m)
|
||||||
|
(QC m a, QC n b) | a == b -> elem m (allExtends env n)
|
||||||
|
|| elem n (allExtends env m)
|
||||||
|
|
||||||
|
(RecType rs, RecType ts) -> and [alpha g a b && l == k --- too strong req
|
||||||
|
| ((l,a),(k,b)) <- zip rs ts]
|
||||||
|
|| -- if fails, try subtyping:
|
||||||
|
all (\ (l,a) ->
|
||||||
|
any (\ (k,b) -> alpha g a b && l == k) ts) rs
|
||||||
|
|
||||||
|
(Table a b, Table c d) -> alpha g a c && alpha g b d
|
||||||
|
(Vr x, Vr y) -> x == y || elem (x,y) g || elem (y,x) g
|
||||||
|
_ -> t == u
|
||||||
|
--- the following should be one-way coercions only. AR 4/1/2001
|
||||||
|
|| elem t sTypes && elem u sTypes
|
||||||
|
|| (t == typeType && u == typePType)
|
||||||
|
|| (u == typeType && t == typePType)
|
||||||
|
|
||||||
|
sTypes = [typeStr, typeTok, typeString]
|
||||||
|
comp = computeLType env
|
||||||
|
|
||||||
|
-- linearization types and defaults
|
||||||
|
|
||||||
|
linTypeOfType :: SourceGrammar -> Ident -> Type -> Check (Context,Type)
|
||||||
|
linTypeOfType cnc m typ = do
|
||||||
|
(cont,cat) <- checkErr $ typeSkeleton typ
|
||||||
|
val <- lookLin cat
|
||||||
|
args <- mapM mkLinArg (zip [0..] cont)
|
||||||
|
return (args, val)
|
||||||
|
where
|
||||||
|
mkLinArg (i,(n,mc@(m,cat))) = do
|
||||||
|
val <- lookLin mc
|
||||||
|
let vars = mkRecType varLabel $ replicate n typeStr
|
||||||
|
symb = argIdent n cat i
|
||||||
|
rec <- checkErr $ errIn ("extending" +++ prt vars +++ "with" +++ prt val) $
|
||||||
|
plusRecType vars val
|
||||||
|
return (symb,rec)
|
||||||
|
lookLin (_,c) = checks [ --- rather: update with defLinType ?
|
||||||
|
checkErr (lookupLincat cnc m c) >>= computeLType cnc
|
||||||
|
,return defLinType
|
||||||
|
]
|
||||||
|
|
||||||
|
{-
|
||||||
|
-- check if a type is complex in variants
|
||||||
|
-- Not so useful as one might think, since variants of a complex type
|
||||||
|
-- can be created indirectly: f (variants {True,False})
|
||||||
|
|
||||||
|
checkIfComplexVariantType :: Term -> Type -> Check ()
|
||||||
|
checkIfComplexVariantType e t = case t of
|
||||||
|
Prod _ _ _ -> cs
|
||||||
|
Table _ _ -> cs
|
||||||
|
RecType (_:_:_) -> cs
|
||||||
|
_ -> return ()
|
||||||
|
where
|
||||||
|
cs = case e of
|
||||||
|
FV (_:_) -> checkWarn $ "Warning:" +++ prt e +++ "has complex type" +++ prt t
|
||||||
|
_ -> return ()
|
||||||
|
|
||||||
|
-}
|
||||||
207
src/GF/Compile/Compile.hs
Normal file
207
src/GF/Compile/Compile.hs
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
module Compile where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Option
|
||||||
|
import PrGrammar
|
||||||
|
import Update
|
||||||
|
import Lookup
|
||||||
|
import Modules
|
||||||
|
import ModDeps
|
||||||
|
import ReadFiles
|
||||||
|
import ShellState
|
||||||
|
import MkResource
|
||||||
|
|
||||||
|
-- the main compiler passes
|
||||||
|
import GetGrammar
|
||||||
|
import Rename
|
||||||
|
import Refresh
|
||||||
|
import CheckGrammar
|
||||||
|
import Optimize
|
||||||
|
import GrammarToCanon
|
||||||
|
import Share
|
||||||
|
|
||||||
|
import qualified CanonToGrammar as CG
|
||||||
|
|
||||||
|
import qualified GFC
|
||||||
|
import qualified MkGFC
|
||||||
|
import GetGFC
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import UseIO
|
||||||
|
import Arch
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- in batch mode: write code in a file
|
||||||
|
|
||||||
|
batchCompile f = liftM fst $ compileModule defOpts emptyShellState f
|
||||||
|
where
|
||||||
|
defOpts = options [beVerbose, emitCode]
|
||||||
|
batchCompileOpt f = liftM fst $ compileModule defOpts emptyShellState f
|
||||||
|
where
|
||||||
|
defOpts = options [beVerbose, emitCode, optimizeCanon]
|
||||||
|
|
||||||
|
batchCompileOld f = compileOld defOpts f
|
||||||
|
where
|
||||||
|
defOpts = options [beVerbose, emitCode]
|
||||||
|
|
||||||
|
-- compile with one module as starting point
|
||||||
|
|
||||||
|
compileModule :: Options -> ShellState -> FilePath ->
|
||||||
|
IOE (GFC.CanonGrammar, (SourceGrammar,[(FilePath,ModTime)]))
|
||||||
|
compileModule opts st file = do
|
||||||
|
let ps = pathListOpts opts
|
||||||
|
ioeIO $ print ps ----
|
||||||
|
let putp = putPointE opts
|
||||||
|
let rfs = readFiles st
|
||||||
|
files <- getAllFiles ps rfs file
|
||||||
|
ioeIO $ print files ----
|
||||||
|
let names = map (fileBody . justFileName) files
|
||||||
|
ioeIO $ print names ----
|
||||||
|
let env0 = compileEnvShSt st names
|
||||||
|
(_,sgr,cgr) <- foldM (compileOne opts) env0 files
|
||||||
|
t <- ioeIO getNowTime
|
||||||
|
return $ (reverseModules cgr, -- to preserve dependency order
|
||||||
|
(reverseModules sgr, --- keepResModules opts sgr, --- keep all so far
|
||||||
|
[(f,t) | f <- files])) -- pass on the time of creation
|
||||||
|
|
||||||
|
compileEnvShSt :: ShellState -> [ModName] -> CompileEnv
|
||||||
|
compileEnvShSt st fs = (0,sgr,cgr) where
|
||||||
|
cgr = MGrammar [m | m@(i,_) <- modules (canModules st), notInc i]
|
||||||
|
sgr = MGrammar [m | m@(i,_) <- modules (srcModules st), notIns i]
|
||||||
|
notInc i = notElem (prt i) $ map fileBody fs
|
||||||
|
notIns i = notElem (prt i) $ map fileBody fs
|
||||||
|
|
||||||
|
pathListOpts :: Options -> [InitPath]
|
||||||
|
pathListOpts opts = maybe [""] pFilePaths $ getOptVal opts pathList
|
||||||
|
|
||||||
|
reverseModules (MGrammar ms) = MGrammar $ reverse ms
|
||||||
|
|
||||||
|
keepResModules :: Options -> SourceGrammar -> SourceGrammar
|
||||||
|
keepResModules opts gr =
|
||||||
|
if oElem retainOpers opts
|
||||||
|
then MGrammar $ reverse [(i,mi) | (i,mi) <- modules gr, isResourceModule mi]
|
||||||
|
else emptyMGrammar
|
||||||
|
|
||||||
|
|
||||||
|
-- the environment
|
||||||
|
|
||||||
|
type CompileEnv = (Int,SourceGrammar, GFC.CanonGrammar)
|
||||||
|
|
||||||
|
emptyCompileEnv :: CompileEnv
|
||||||
|
emptyCompileEnv = (0,emptyMGrammar,emptyMGrammar)
|
||||||
|
|
||||||
|
extendCompileEnvInt (_,MGrammar ss, MGrammar cs) (k,sm,cm) =
|
||||||
|
return (k,MGrammar (sm:ss), MGrammar (cm:cs)) --- reverse later
|
||||||
|
|
||||||
|
extendCompileEnv (k,s,c) (sm,cm) = extendCompileEnvInt (k,s,c) (k,sm,cm)
|
||||||
|
|
||||||
|
compileOne :: Options -> CompileEnv -> FullPath -> IOE CompileEnv
|
||||||
|
compileOne opts env file = do
|
||||||
|
|
||||||
|
let putp = putPointE opts
|
||||||
|
let gf = fileSuffix file
|
||||||
|
let path = justInitPath file
|
||||||
|
let name = fileBody file
|
||||||
|
|
||||||
|
case gf of
|
||||||
|
-- for canonical gf, just read the file and update environment
|
||||||
|
"gfc" -> do
|
||||||
|
cm <- putp ("+ reading" +++ file) $ getCanonModule file
|
||||||
|
sm <- ioeErr $ CG.canon2sourceModule cm
|
||||||
|
extendCompileEnv env (sm, cm)
|
||||||
|
|
||||||
|
-- for compiled resource, parse and organize, then update environment
|
||||||
|
"gfr" -> do
|
||||||
|
sm0 <- putp ("| parsing" +++ file) $ getSourceModule file
|
||||||
|
let mos = case env of (_,gr,_) -> modules gr
|
||||||
|
sm <- {- putp "creating indirections" $ -} ioeErr $ extendModule mos sm0
|
||||||
|
let gfc = gfcFile name
|
||||||
|
cm <- putp ("+ reading" +++ gfc) $ getCanonModule gfc
|
||||||
|
extendCompileEnv env (sm,cm)
|
||||||
|
|
||||||
|
-- for gf source, do full compilation
|
||||||
|
_ -> do
|
||||||
|
sm0 <- putp ("- parsing" +++ file) $ getSourceModule file
|
||||||
|
(k',sm) <- makeSourceModule opts env sm0
|
||||||
|
cm <- putp " generating code... " $ generateModuleCode opts path sm
|
||||||
|
extendCompileEnvInt env (k',sm,cm)
|
||||||
|
|
||||||
|
-- dispatch reused resource at early stage
|
||||||
|
|
||||||
|
makeSourceModule :: Options -> CompileEnv -> SourceModule -> IOE (Int,SourceModule)
|
||||||
|
makeSourceModule opts env@(k,gr,can) mo@(i,mi) = case mi of
|
||||||
|
|
||||||
|
ModMod m -> case mtype m of
|
||||||
|
MTReuse c -> do
|
||||||
|
sm <- ioeErr $ makeReuse gr i (extends m) c
|
||||||
|
let mo2 = (i, ModMod sm)
|
||||||
|
mos = modules gr
|
||||||
|
putp " type checking reused" $ ioeErr $ showCheckModule mos mo2
|
||||||
|
return $ (k,mo2)
|
||||||
|
_ -> compileSourceModule opts env mo
|
||||||
|
where
|
||||||
|
putp = putPointE opts
|
||||||
|
|
||||||
|
compileSourceModule :: Options -> CompileEnv -> SourceModule ->
|
||||||
|
IOE (Int,SourceModule)
|
||||||
|
compileSourceModule opts env@(k,gr,can) mo@(i,mi) = do
|
||||||
|
|
||||||
|
let putp = putPointE opts
|
||||||
|
mos = modules gr
|
||||||
|
|
||||||
|
mo2:_ <- putp " renaming " $ ioeErr $ renameModule mos mo
|
||||||
|
|
||||||
|
(mo3:_,warnings) <- putp " type checking" $ ioeErr $ showCheckModule mos mo2
|
||||||
|
putStrE warnings
|
||||||
|
|
||||||
|
(k',mo3r:_) <- ioeErr $ refreshModule (k,mos) mo3
|
||||||
|
|
||||||
|
mo4:_ <- putp " optimizing" $ ioeErr $ evalModule mos mo3r
|
||||||
|
|
||||||
|
return (k',mo4)
|
||||||
|
|
||||||
|
generateModuleCode :: Options -> InitPath -> SourceModule -> IOE GFC.CanonModule
|
||||||
|
generateModuleCode opts path minfo@(name,info) = do
|
||||||
|
let pname = prefixPathName path (prt name)
|
||||||
|
minfo0 <- ioeErr $ redModInfo minfo
|
||||||
|
minfo' <- return $ if optim
|
||||||
|
then shareModule fullOpt minfo0 -- parametrization and sharing
|
||||||
|
else shareModule basicOpt minfo0 -- sharing only
|
||||||
|
|
||||||
|
-- for resource, also emit gfr
|
||||||
|
case info of
|
||||||
|
ModMod m | mtype m == MTResource && emit && nomulti -> do
|
||||||
|
let (file,out) = (gfrFile pname, prGrammar (MGrammar [minfo]))
|
||||||
|
ioeIO $ writeFile file out >> putStr (" wrote file" +++ file)
|
||||||
|
_ -> return ()
|
||||||
|
(file,out) <- do
|
||||||
|
code <- return $ MkGFC.prCanonModInfo minfo'
|
||||||
|
return (gfcFile pname, code)
|
||||||
|
if emit && nomulti
|
||||||
|
then ioeIO $ writeFile file out >> putStr (" wrote file" +++ file)
|
||||||
|
else return ()
|
||||||
|
return minfo'
|
||||||
|
where
|
||||||
|
nomulti = not $ oElem makeMulti opts
|
||||||
|
emit = oElem emitCode opts
|
||||||
|
optim = oElem optimizeCanon opts
|
||||||
|
|
||||||
|
-- for old GF: sort into modules, write files, compile as usual
|
||||||
|
|
||||||
|
compileOld :: Options -> FilePath -> IOE GFC.CanonGrammar
|
||||||
|
compileOld opts file = do
|
||||||
|
let putp = putPointE opts
|
||||||
|
grammar1 <- putp ("- parsing old gf" +++ file) $ getOldGrammar file
|
||||||
|
files <- mapM writeNewGF $ modules grammar1
|
||||||
|
(_,_,grammar) <- foldM (compileOne opts) emptyCompileEnv files
|
||||||
|
return grammar
|
||||||
|
|
||||||
|
writeNewGF :: SourceModule -> IOE FilePath
|
||||||
|
writeNewGF m@(i,_) = do
|
||||||
|
let file = gfFile $ prt i
|
||||||
|
ioeIO $ writeFile file $ prGrammar (MGrammar [m])
|
||||||
|
ioeIO $ putStrLn $ "wrote file" +++ file
|
||||||
|
return file
|
||||||
|
|
||||||
77
src/GF/Compile/Extend.hs
Normal file
77
src/GF/Compile/Extend.hs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
module Extend where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import PrGrammar
|
||||||
|
import Modules
|
||||||
|
import Update
|
||||||
|
import Macros
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- AR 14/5/2003
|
||||||
|
|
||||||
|
-- The top-level function $extendModInfo$
|
||||||
|
-- extends a module symbol table by indirections to the module it extends
|
||||||
|
|
||||||
|
extendModInfo :: Ident -> SourceModInfo -> SourceModInfo -> Err SourceModInfo
|
||||||
|
extendModInfo name old new = case (old,new) of
|
||||||
|
(ModMod m0, ModMod (Module mt fs _ ops js)) -> do
|
||||||
|
testErr (mtype m0 == mt) ("illegal extension type at module" +++ show name)
|
||||||
|
js' <- extendMod name (jments m0) js
|
||||||
|
return $ ModMod (Module mt fs Nothing ops js)
|
||||||
|
|
||||||
|
-- this is what happens when extending a module: new information is inserted,
|
||||||
|
-- and the process is interrupted if unification fails
|
||||||
|
|
||||||
|
extendMod :: Ident -> BinTree (Ident,Info) -> BinTree (Ident,Info) ->
|
||||||
|
Err (BinTree (Ident,Info))
|
||||||
|
extendMod name old new =
|
||||||
|
foldM (tryInsert (extendAnyInfo name) (indirInfo name)) new $ tree2list old
|
||||||
|
|
||||||
|
indirInfo :: Ident -> Info -> Info
|
||||||
|
indirInfo n info = AnyInd b n' where
|
||||||
|
(b,n') = case info of
|
||||||
|
ResValue _ -> (True,n)
|
||||||
|
ResParam _ -> (True,n)
|
||||||
|
AnyInd b k -> (b,k)
|
||||||
|
_ -> (False,n) ---- canonical in Abs
|
||||||
|
|
||||||
|
{- ----
|
||||||
|
case info of
|
||||||
|
AbsFun pty ptr -> AbsFun (perhIndir n pty) (perhIndir n ptr)
|
||||||
|
---- find a suitable indirection for cat info!
|
||||||
|
|
||||||
|
ResOper pty ptr -> ResOper (perhIndir n pty) (perhIndir n ptr)
|
||||||
|
ResParam pp -> ResParam (perhIndir n pp)
|
||||||
|
_ -> info
|
||||||
|
|
||||||
|
CncCat pty ptr ppr -> CncCat (perhIndir n pty) (perhIndir n ptr) (perhIndir n ppr)
|
||||||
|
CncFun m ptr ppr -> CncFun m (perhIndir n ptr) (perhIndir n ppr)
|
||||||
|
-}
|
||||||
|
|
||||||
|
perhIndir :: Ident -> Perh a -> Perh a
|
||||||
|
perhIndir n p = case p of
|
||||||
|
Yes _ -> May n
|
||||||
|
_ -> p
|
||||||
|
|
||||||
|
extendAnyInfo :: Ident -> Info -> Info -> Err Info
|
||||||
|
extendAnyInfo n i j = case (i,j) of
|
||||||
|
(AbsCat mc1 mf1, AbsCat mc2 mf2) ->
|
||||||
|
liftM2 AbsCat (updatePerhaps n mc1 mc2) (updatePerhaps n mf1 mf2) --- add cstrs
|
||||||
|
(AbsFun mt1 md1, AbsFun mt2 md2) ->
|
||||||
|
liftM2 AbsFun (updatePerhaps n mt1 mt2) (updatePerhaps n md1 md2) --- add defs
|
||||||
|
|
||||||
|
(ResParam mt1, ResParam mt2) -> liftM ResParam $ updatePerhaps n mt1 mt2
|
||||||
|
(ResValue mt1, ResValue mt2) -> liftM ResValue $ updatePerhaps n mt1 mt2
|
||||||
|
(ResOper mt1 m1, ResOper mt2 m2) ->
|
||||||
|
liftM2 ResOper (updatePerhaps n mt1 mt2) (updatePerhaps n m1 m2)
|
||||||
|
|
||||||
|
(CncCat mc1 mf1 mp1, CncCat mc2 mf2 mp2) ->
|
||||||
|
liftM3 CncCat (updatePerhaps n mc1 mc2)
|
||||||
|
(updatePerhaps n mf1 mf2) (updatePerhaps n mp1 mp2)
|
||||||
|
(CncFun m mt1 md1, CncFun _ mt2 md2) ->
|
||||||
|
liftM2 (CncFun m) (updatePerhaps n mt1 mt2) (updatePerhaps n md1 md2)
|
||||||
|
|
||||||
|
_ -> Bad $ "cannot unify information for" +++ show n
|
||||||
71
src/GF/Compile/GetGrammar.hs
Normal file
71
src/GF/Compile/GetGrammar.hs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
module GetGrammar where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import qualified ErrM as E ----
|
||||||
|
|
||||||
|
import UseIO
|
||||||
|
import Grammar
|
||||||
|
import Modules
|
||||||
|
import PrGrammar
|
||||||
|
import qualified AbsGF as A
|
||||||
|
import SourceToGrammar
|
||||||
|
---- import Macros
|
||||||
|
---- import Rename
|
||||||
|
import Option
|
||||||
|
--- import Custom
|
||||||
|
import ParGF
|
||||||
|
|
||||||
|
import ReadFiles ----
|
||||||
|
|
||||||
|
import List (nub)
|
||||||
|
import Monad (foldM)
|
||||||
|
|
||||||
|
-- this module builds the internal GF grammar that is sent to the type checker
|
||||||
|
|
||||||
|
getSourceModule :: FilePath -> IOE SourceModule
|
||||||
|
getSourceModule file = do
|
||||||
|
string <- readFileIOE file
|
||||||
|
let tokens = myLexer string
|
||||||
|
mo1 <- ioeErr $ err2err $ pModDef tokens
|
||||||
|
ioeErr $ transModDef mo1
|
||||||
|
|
||||||
|
|
||||||
|
-- for old GF format with includes
|
||||||
|
|
||||||
|
getOldGrammar :: FilePath -> IOE SourceGrammar
|
||||||
|
getOldGrammar file = do
|
||||||
|
defs <- parseOldGrammarFiles file
|
||||||
|
let g = A.OldGr A.NoIncl defs
|
||||||
|
ioeErr $ transOldGrammar g file
|
||||||
|
|
||||||
|
parseOldGrammarFiles :: FilePath -> IOE [A.TopDef]
|
||||||
|
parseOldGrammarFiles file = do
|
||||||
|
putStrE $ "reading grammar of old format" +++ file
|
||||||
|
(_, g) <- getImports "" ([],[]) file
|
||||||
|
return g -- now we can throw away includes
|
||||||
|
where
|
||||||
|
getImports oldInitPath (oldImps, oldG) f = do
|
||||||
|
(path,s) <- readFileLibraryIOE oldInitPath f
|
||||||
|
if not (elem path oldImps)
|
||||||
|
then do
|
||||||
|
(imps,g) <- parseOldGrammar path
|
||||||
|
foldM (getImports (initFilePath path)) (path : oldImps, g ++ oldG) imps
|
||||||
|
else
|
||||||
|
return (oldImps, oldG)
|
||||||
|
|
||||||
|
parseOldGrammar :: FilePath -> IOE ([FilePath],[A.TopDef])
|
||||||
|
parseOldGrammar file = do
|
||||||
|
putStrE $ "reading old file" +++ file
|
||||||
|
s <- ioeIO $ readFileIf file
|
||||||
|
A.OldGr incl topdefs <- ioeErr $ err2err $ pOldGrammar $ myLexer $ fixNewlines s
|
||||||
|
includes <- ioeErr $ transInclude incl
|
||||||
|
return (includes, topdefs)
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
err2err :: E.Err a -> Err a
|
||||||
|
err2err (E.Ok v) = Ok v
|
||||||
|
err2err (E.Bad s) = Bad s
|
||||||
|
|
||||||
|
ioeEErr = ioeErr . err2err
|
||||||
|
|
||||||
224
src/GF/Compile/GrammarToCanon.hs
Normal file
224
src/GF/Compile/GrammarToCanon.hs
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
module GrammarToCanon where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Zipper
|
||||||
|
import Option
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import PrGrammar
|
||||||
|
import Modules
|
||||||
|
import Macros
|
||||||
|
import qualified AbsGFC as G
|
||||||
|
import qualified GFC as C
|
||||||
|
import MkGFC
|
||||||
|
---- import Alias
|
||||||
|
import qualified PrintGFC as P
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- compilation of optimized grammars to canonical GF. AR 5/10/2001 -- 12/5/2003
|
||||||
|
|
||||||
|
-- This is the top-level function printing a gfc file
|
||||||
|
|
||||||
|
showGFC :: SourceGrammar -> String
|
||||||
|
showGFC = err id id . liftM (P.printTree . grammar2canon) . redGrammar
|
||||||
|
|
||||||
|
-- any grammar, first trying without dependent types
|
||||||
|
|
||||||
|
-- abstract syntax without dependent types
|
||||||
|
|
||||||
|
redGrammar :: SourceGrammar -> Err C.CanonGrammar
|
||||||
|
redGrammar (MGrammar gr) = liftM MGrammar $ mapM redModInfo gr
|
||||||
|
|
||||||
|
redModInfo :: (Ident, SourceModInfo) -> Err (Ident, C.CanonModInfo)
|
||||||
|
redModInfo (c,info) = do
|
||||||
|
c' <- redIdent c
|
||||||
|
info' <- case info of
|
||||||
|
ModMod m -> do
|
||||||
|
(e,os) <- redExtOpen m
|
||||||
|
flags <- mapM redFlag $ flags m
|
||||||
|
(a,mt) <- case mtype m of
|
||||||
|
MTConcrete a -> do
|
||||||
|
a' <- redIdent a
|
||||||
|
return (a', MTConcrete a')
|
||||||
|
MTAbstract -> return (c',MTAbstract) --- c' not needed
|
||||||
|
MTResource -> return (c',MTResource) --- c' not needed
|
||||||
|
defss <- mapM (redInfo a) $ tree2list $ jments m
|
||||||
|
defs <- return $ sorted2tree $ concat defss -- sorted, but reduced
|
||||||
|
return $ ModMod $ Module mt flags e os defs
|
||||||
|
return (c',info')
|
||||||
|
where
|
||||||
|
redExtOpen m = do
|
||||||
|
e' <- case extends m of
|
||||||
|
Just e -> liftM Just $ redIdent e
|
||||||
|
_ -> return Nothing
|
||||||
|
os' <- mapM (\ (OQualif _ i) -> liftM OSimple (redIdent i)) $ opens m
|
||||||
|
return (e',os')
|
||||||
|
|
||||||
|
redInfo :: Ident -> (Ident,Info) -> Err [(Ident,C.Info)]
|
||||||
|
redInfo am (c,info) = errIn ("translating definition of" +++ prt c) $ do
|
||||||
|
c' <- redIdent c
|
||||||
|
case info of
|
||||||
|
AbsCat (Yes cont) pfs -> do
|
||||||
|
returns c' $ C.AbsCat cont [] ---- constrs
|
||||||
|
AbsFun (Yes typ) pdf -> do
|
||||||
|
returns c' $ C.AbsFun typ (Eqs []) ---- df
|
||||||
|
|
||||||
|
ResParam (Yes ps) -> do
|
||||||
|
ps' <- mapM redParam ps
|
||||||
|
returns c' $ C.ResPar ps'
|
||||||
|
|
||||||
|
CncCat pty ptr ppr -> case (pty,ptr) of
|
||||||
|
(Yes ty, Yes (Abs _ t)) -> do
|
||||||
|
ty' <- redCType ty
|
||||||
|
trm' <- redCTerm t
|
||||||
|
ppr' <- return $ G.FV [] ---- redCTerm
|
||||||
|
return [(c', C.CncCat ty' trm' ppr')]
|
||||||
|
_ -> prtBad "cannot reduce rule for" c
|
||||||
|
|
||||||
|
CncFun mt ptr ppr -> case (mt,ptr) of
|
||||||
|
(Just (cat,_), Yes trm) -> do
|
||||||
|
cat' <- redIdent cat
|
||||||
|
(xx,body,_) <- termForm trm
|
||||||
|
xx' <- mapM redArgvar xx
|
||||||
|
body' <- errIn (prt body) $ redCTerm body ---- debug
|
||||||
|
ppr' <- return $ G.FV [] ---- redCTerm
|
||||||
|
return [(c',C.CncFun (G.CIQ am cat') xx' body' ppr')]
|
||||||
|
_ -> prtBad ("cannot reduce rule" +++ show info +++ "for") c ---- debug
|
||||||
|
|
||||||
|
AnyInd s b -> do
|
||||||
|
b' <- redIdent b
|
||||||
|
returns c' $ C.AnyInd s b'
|
||||||
|
|
||||||
|
_ -> return [] --- retain some operations
|
||||||
|
where
|
||||||
|
returns f i = return [(f,i)]
|
||||||
|
|
||||||
|
redQIdent :: QIdent -> Err G.CIdent
|
||||||
|
redQIdent (m,c) = return $ G.CIQ m c
|
||||||
|
|
||||||
|
redIdent :: Ident -> Err Ident
|
||||||
|
redIdent x
|
||||||
|
| isWildIdent x = return $ identC "h_" --- needed in declarations
|
||||||
|
| otherwise = return $ identC $ prt x ---
|
||||||
|
|
||||||
|
redFlag :: Option -> Err G.Flag
|
||||||
|
redFlag (Opt (f,[x])) = return $ G.Flg (identC f) (identC x)
|
||||||
|
redFlag o = Bad $ "cannot reduce option" +++ prOpt o
|
||||||
|
|
||||||
|
redDecl :: Decl -> Err G.Decl
|
||||||
|
redDecl (x,a) = liftM2 G.Decl (redIdent x) (redType a)
|
||||||
|
|
||||||
|
redType :: Type -> Err G.Exp
|
||||||
|
redType = redTerm
|
||||||
|
|
||||||
|
redTerm :: Type -> Err G.Exp
|
||||||
|
redTerm t = return $ rtExp t
|
||||||
|
|
||||||
|
-- resource
|
||||||
|
|
||||||
|
redParam :: Param -> Err G.ParDef
|
||||||
|
redParam (c,cont) = do
|
||||||
|
c' <- redIdent c
|
||||||
|
cont' <- mapM (redCType . snd) cont
|
||||||
|
return $ G.ParD c' cont'
|
||||||
|
|
||||||
|
redArgvar :: Ident -> Err G.ArgVar
|
||||||
|
redArgvar x = case x of
|
||||||
|
IA (x,i) -> return $ G.A (identC x) (toInteger i)
|
||||||
|
IAV (x,b,i) -> return $ G.AB (identC x) (toInteger b) (toInteger i)
|
||||||
|
_ -> Bad $ "cannot reduce" +++ show x +++ "as argument variable"
|
||||||
|
|
||||||
|
redLindef :: Term -> Err G.Term
|
||||||
|
redLindef t = case t of
|
||||||
|
Abs x b -> redCTerm b ---
|
||||||
|
_ -> redCTerm t
|
||||||
|
|
||||||
|
redCType :: Type -> Err G.CType
|
||||||
|
redCType t = case t of
|
||||||
|
RecType lbs -> do
|
||||||
|
let (ls,ts) = unzip lbs
|
||||||
|
ls' = map redLabel ls
|
||||||
|
ts' <- mapM redCType ts
|
||||||
|
return $ G.RecType $ map (uncurry G.Lbg) $ zip ls' ts'
|
||||||
|
Table p v -> liftM2 G.Table (redCType p) (redCType v)
|
||||||
|
Q m c -> liftM G.Cn $ redQIdent (m,c)
|
||||||
|
QC m c -> liftM G.Cn $ redQIdent (m,c)
|
||||||
|
Sort "Str" -> return $ G.TStr
|
||||||
|
_ -> prtBad "cannot reduce to canonical the type" t
|
||||||
|
|
||||||
|
redCTerm :: Term -> Err G.Term
|
||||||
|
redCTerm t = case t of
|
||||||
|
Vr x -> liftM G.Arg $ redArgvar x
|
||||||
|
App _ _ -> do -- only constructor applications can remain
|
||||||
|
(_,c,xx) <- termForm t
|
||||||
|
xx' <- mapM redCTerm xx
|
||||||
|
case c of
|
||||||
|
QC p c -> liftM2 G.Con (redQIdent (p,c)) (return xx')
|
||||||
|
_ -> prtBad "expected constructor head instead of" c
|
||||||
|
Q p c -> liftM G.I (redQIdent (p,c))
|
||||||
|
QC p c -> liftM2 G.Con (redQIdent (p,c)) (return [])
|
||||||
|
R rs -> do
|
||||||
|
let (ls,tts) = unzip rs
|
||||||
|
ls' = map redLabel ls
|
||||||
|
ts <- mapM (redCTerm . snd) tts
|
||||||
|
return $ G.R $ map (uncurry G.Ass) $ zip ls' ts
|
||||||
|
P tr l -> do
|
||||||
|
tr' <- redCTerm tr
|
||||||
|
return $ G.P tr' (redLabel l)
|
||||||
|
T i cs -> do
|
||||||
|
ty <- getTableType i
|
||||||
|
ty' <- redCType ty
|
||||||
|
let (ps,ts) = unzip cs
|
||||||
|
ps' <- mapM redPatt ps
|
||||||
|
ts' <- mapM redCTerm ts
|
||||||
|
return $ G.T ty' $ map (uncurry G.Cas) $ zip (map singleton ps') ts'
|
||||||
|
S u v -> liftM2 G.S (redCTerm u) (redCTerm v)
|
||||||
|
K s -> return $ G.K (G.KS s)
|
||||||
|
C u v -> liftM2 G.C (redCTerm u) (redCTerm v)
|
||||||
|
FV ts -> liftM G.FV $ mapM redCTerm ts
|
||||||
|
--- Ready ss -> return $ G.Ready [redStr ss] --- obsolete
|
||||||
|
|
||||||
|
Alts (d,vs) -> do ---
|
||||||
|
d' <- redCTermTok d
|
||||||
|
vs' <- mapM redVariant vs
|
||||||
|
return $ G.K $ G.KP d' vs'
|
||||||
|
|
||||||
|
Empty -> return $ G.E
|
||||||
|
|
||||||
|
--- Strs ss -> return $ G.Strs [s | K s <- ss] ---
|
||||||
|
|
||||||
|
---- Glue obsolete in canon, should not occur here
|
||||||
|
Glue x y -> redCTerm (C x y)
|
||||||
|
|
||||||
|
_ -> Bad ("cannot reduce term" +++ prt t)
|
||||||
|
|
||||||
|
redPatt :: Patt -> Err G.Patt
|
||||||
|
redPatt p = case p of
|
||||||
|
PP m c ps -> liftM2 G.PC (redQIdent (m,c)) (mapM redPatt ps)
|
||||||
|
PR rs -> do
|
||||||
|
let (ls,tts) = unzip rs
|
||||||
|
ls' = map redLabel ls
|
||||||
|
ts <- mapM redPatt tts
|
||||||
|
return $ G.PR $ map (uncurry G.PAss) $ zip ls' ts
|
||||||
|
PT _ q -> redPatt q
|
||||||
|
_ -> prtBad "cannot reduce pattern" p
|
||||||
|
|
||||||
|
redLabel :: Label -> G.Label
|
||||||
|
redLabel (LIdent s) = G.L $ identC s
|
||||||
|
redLabel (LVar i) = G.LV $ toInteger i
|
||||||
|
|
||||||
|
redVariant :: (Term, Term) -> Err G.Variant
|
||||||
|
redVariant (v,c) = do
|
||||||
|
v' <- redCTermTok v
|
||||||
|
c' <- redCTermTok c
|
||||||
|
return $ G.Var v' c'
|
||||||
|
|
||||||
|
redCTermTok :: Term -> Err [String]
|
||||||
|
redCTermTok t = case t of
|
||||||
|
K s -> return [s]
|
||||||
|
Empty -> return []
|
||||||
|
C a b -> liftM2 (++) (redCTermTok a) (redCTermTok b)
|
||||||
|
Strs ss -> return [s | K s <- ss] ---
|
||||||
|
_ -> prtBad "cannot get strings from term" t
|
||||||
|
|
||||||
75
src/GF/Compile/MkResource.hs
Normal file
75
src/GF/Compile/MkResource.hs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
module MkResource where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Modules
|
||||||
|
import Macros
|
||||||
|
import PrGrammar
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- extracting resource r from abstract + concrete syntax
|
||||||
|
-- AR 21/8/2002 -- 22/6/2003 for GF with modules
|
||||||
|
|
||||||
|
makeReuse :: SourceGrammar -> Ident -> Maybe Ident -> Ident -> Err SourceRes
|
||||||
|
makeReuse gr r me c = do
|
||||||
|
mc <- lookupModule gr c
|
||||||
|
|
||||||
|
flags <- return [] --- no flags are passed: they would not make sense
|
||||||
|
|
||||||
|
(ops,jms) <- case mc of
|
||||||
|
ModMod m -> case mtype m of
|
||||||
|
MTConcrete a -> do
|
||||||
|
ma <- lookupModule gr a
|
||||||
|
jmsA <- case ma of
|
||||||
|
ModMod m' -> return $ jments m'
|
||||||
|
_ -> prtBad "expected abstract to be the type of" a
|
||||||
|
liftM ((,) (opens m)) $ mkResDefs r a me (extends m) jmsA (jments m)
|
||||||
|
_ -> prtBad "expected concrete to be the type of" c
|
||||||
|
_ -> prtBad "expected concrete to be the type of" c
|
||||||
|
|
||||||
|
return $ Module MTResource flags me ops jms
|
||||||
|
|
||||||
|
mkResDefs :: Ident -> Ident -> Maybe Ident -> Maybe Ident ->
|
||||||
|
BinTree (Ident,Info) -> BinTree (Ident,Info) ->
|
||||||
|
Err (BinTree (Ident,Info))
|
||||||
|
mkResDefs r a mext maext abs cnc = mapMTree mkOne abs where
|
||||||
|
|
||||||
|
mkOne (f,info) = case info of
|
||||||
|
AbsCat _ _ -> do
|
||||||
|
typ <- err (const (return defLinType)) return $ look f
|
||||||
|
return (f, ResOper (Yes typeType) (Yes typ))
|
||||||
|
AbsFun (Yes typ0) _ -> do
|
||||||
|
trm <- look f
|
||||||
|
typ <- redirTyp typ0 --- if isHardType typ0 then compute typ0 else ...
|
||||||
|
return (f, ResOper (Yes typ) (Yes trm))
|
||||||
|
AnyInd b _ -> case mext of
|
||||||
|
Just ext -> return (f,AnyInd b ext)
|
||||||
|
_ -> prtBad "no indirection possible in" r
|
||||||
|
|
||||||
|
look f = do
|
||||||
|
info <- lookupTree prt f cnc
|
||||||
|
case info of
|
||||||
|
CncCat (Yes ty) _ _ -> return ty
|
||||||
|
CncCat _ _ _ -> return defLinType
|
||||||
|
CncFun _ (Yes tr) _ -> return tr
|
||||||
|
_ -> prtBad "not enough information to reuse" f
|
||||||
|
|
||||||
|
-- type constant qualifications changed from abstract to resource
|
||||||
|
redirTyp ty = case ty of
|
||||||
|
Q n c | n == a -> return $ Q r c
|
||||||
|
Q n c | Just n == maext -> case mext of
|
||||||
|
Just ext -> return $ Q ext c
|
||||||
|
_ -> prtBad "no indirection of type possible in" r
|
||||||
|
_ -> composOp redirTyp ty
|
||||||
|
|
||||||
|
{-
|
||||||
|
-- for nicer printing of type signatures: preserves synonyms if not HO/dep type
|
||||||
|
|
||||||
|
isHardType t = case t of
|
||||||
|
Prod x a b -> not (isWildIdent x) || isHardType a || isHardType b
|
||||||
|
App _ _ -> True
|
||||||
|
_ -> False
|
||||||
|
-}
|
||||||
88
src/GF/Compile/ModDeps.hs
Normal file
88
src/GF/Compile/ModDeps.hs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
module ModDeps where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Option
|
||||||
|
import PrGrammar
|
||||||
|
import Update
|
||||||
|
import Lookup
|
||||||
|
import Modules
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- AR 13/5/2003
|
||||||
|
|
||||||
|
-- to check uniqueness of module names and import names, the
|
||||||
|
-- appropriateness of import and extend types,
|
||||||
|
-- to build a dependency graph of modules, and to sort them topologically
|
||||||
|
|
||||||
|
mkSourceGrammar :: [(Ident,SourceModInfo)] -> Err SourceGrammar
|
||||||
|
mkSourceGrammar ms = do
|
||||||
|
let ns = map fst ms
|
||||||
|
checkUniqueErr ns
|
||||||
|
mapM (checkUniqueImportNames ns . snd) ms
|
||||||
|
deps <- moduleDeps ms
|
||||||
|
deplist <- either
|
||||||
|
return
|
||||||
|
(\ms -> Bad $ "circular modules" +++ unwords (map show ms)) $
|
||||||
|
topoTest deps
|
||||||
|
return $ MGrammar [(m, maybe undefined id $ lookup m ms) | IdentM m _ <- deplist]
|
||||||
|
|
||||||
|
checkUniqueErr :: (Show i, Eq i) => [i] -> Err ()
|
||||||
|
checkUniqueErr ms = do
|
||||||
|
let msg = checkUnique ms
|
||||||
|
if null msg then return () else Bad $ unlines msg
|
||||||
|
|
||||||
|
-- check that import names don't clash with module names
|
||||||
|
|
||||||
|
checkUniqueImportNames :: [Ident] -> SourceModInfo -> Err ()
|
||||||
|
checkUniqueImportNames ns mo = case mo of
|
||||||
|
ModMod m -> test [n | OQualif n v <- opens m, n /= v]
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
test ms = testErr (all (`notElem` ns) ms)
|
||||||
|
("import names clashing with module names among" +++
|
||||||
|
unwords (map prt ms))
|
||||||
|
|
||||||
|
-- to decide what modules immediately depend on what, and check if the
|
||||||
|
-- dependencies are appropriate
|
||||||
|
|
||||||
|
type Dependencies = [(IdentM Ident,[IdentM Ident])]
|
||||||
|
|
||||||
|
moduleDeps :: [(Ident,SourceModInfo)] -> Err Dependencies
|
||||||
|
moduleDeps ms = mapM deps ms where
|
||||||
|
deps (c,mi) = errIn ("checking dependencies of module" +++ prt c) $ case mi of
|
||||||
|
ModMod m -> case mtype m of
|
||||||
|
MTConcrete a -> do
|
||||||
|
aty <- lookupModuleType gr a
|
||||||
|
testErr (aty == MTAbstract) "the for-module is not an abstract syntax"
|
||||||
|
chDep (IdentM c (MTConcrete a))
|
||||||
|
(extends m) (MTConcrete a) (opens m) MTResource
|
||||||
|
t -> chDep (IdentM c t) (extends m) t (opens m) t
|
||||||
|
|
||||||
|
chDep it es ety os oty = do
|
||||||
|
ests <- case es of
|
||||||
|
Just e -> liftM singleton $ lookupModuleType gr e
|
||||||
|
_ -> return []
|
||||||
|
testErr (all (compatMType ety) ests) "inappropriate extension module type"
|
||||||
|
osts <- mapM (lookupModuleType gr . openedModule) os
|
||||||
|
testErr (all (==oty) osts) "inappropriate open module type"
|
||||||
|
let ab = case it of
|
||||||
|
IdentM _ (MTConcrete a) -> [IdentM a MTAbstract]
|
||||||
|
_ -> [] ----
|
||||||
|
return (it, ab ++
|
||||||
|
[IdentM e ety | Just e <- [es]] ++
|
||||||
|
[IdentM (openedModule o) oty | o <- os])
|
||||||
|
|
||||||
|
-- check for superficial compatibility, not submodule relation etc
|
||||||
|
compatMType mt0 mt = case (mt0,mt) of
|
||||||
|
(MTConcrete _, MTConcrete _) -> True
|
||||||
|
(MTResourceImpl _, MTResourceImpl _) -> True
|
||||||
|
(MTReuse _, MTReuse _) -> True
|
||||||
|
---- some more
|
||||||
|
_ -> mt0 == mt
|
||||||
|
|
||||||
|
gr = MGrammar ms --- hack
|
||||||
171
src/GF/Compile/Optimize.hs
Normal file
171
src/GF/Compile/Optimize.hs
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
module Optimize where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Modules
|
||||||
|
import PrGrammar
|
||||||
|
import Macros
|
||||||
|
import Lookup
|
||||||
|
import Refresh
|
||||||
|
import Compute
|
||||||
|
import CheckGrammar
|
||||||
|
import Update
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import CheckM
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
import List
|
||||||
|
|
||||||
|
-- partial evaluation of concrete syntax. AR 6/2001 -- 16/5/2003
|
||||||
|
{-
|
||||||
|
evalGrammar :: SourceGrammar -> Err SourceGrammar
|
||||||
|
evalGrammar gr = do
|
||||||
|
gr2 <- refreshGrammar gr
|
||||||
|
mos <- foldM evalModule [] $ modules gr2
|
||||||
|
return $ MGrammar $ reverse mos
|
||||||
|
-}
|
||||||
|
evalModule :: [(Ident,SourceModInfo)] -> (Ident,SourceModInfo) ->
|
||||||
|
Err [(Ident,SourceModInfo)]
|
||||||
|
evalModule ms mo@(name,mod) = case mod of
|
||||||
|
|
||||||
|
ModMod (Module mt fs me ops js) -> case mt of
|
||||||
|
MTResource -> do
|
||||||
|
let deps = allOperDependencies name js
|
||||||
|
ids <- topoSortOpers deps
|
||||||
|
MGrammar (mod' : _) <- foldM evalOp gr ids
|
||||||
|
return $ mod' : ms
|
||||||
|
MTConcrete a -> do
|
||||||
|
js' <- mapMTree (evalCncInfo gr0 name a) js
|
||||||
|
return $ (name, ModMod (Module mt fs me ops js')) : ms
|
||||||
|
|
||||||
|
_ -> return $ (name,mod):ms
|
||||||
|
where
|
||||||
|
gr0 = MGrammar $ ms
|
||||||
|
gr = MGrammar $ (name,mod) : ms
|
||||||
|
|
||||||
|
evalOp g@(MGrammar ((_, ModMod m) : _)) i = do
|
||||||
|
info <- lookupTree prt i $ jments m
|
||||||
|
info' <- evalResInfo gr (i,info)
|
||||||
|
return $ updateRes g name i info'
|
||||||
|
|
||||||
|
-- only operations need be compiled in a resource, and this is local to each
|
||||||
|
-- definition since the module is traversed in topological order
|
||||||
|
|
||||||
|
evalResInfo :: SourceGrammar -> (Ident,Info) -> Err Info
|
||||||
|
evalResInfo gr (c,info) = case info of
|
||||||
|
|
||||||
|
ResOper pty pde -> eIn "operation" $ do
|
||||||
|
pde' <- case pde of
|
||||||
|
Yes de -> liftM yes $ comp de
|
||||||
|
_ -> return pde
|
||||||
|
return $ ResOper pty pde'
|
||||||
|
|
||||||
|
_ -> return info
|
||||||
|
where
|
||||||
|
comp = computeConcrete gr
|
||||||
|
eIn cat = errIn ("Error optimizing" +++ cat +++ prt c +++ ":")
|
||||||
|
|
||||||
|
|
||||||
|
evalCncInfo ::
|
||||||
|
SourceGrammar -> Ident -> Ident -> (Ident,Info) -> Err (Ident,Info)
|
||||||
|
evalCncInfo gr cnc abs (c,info) = case info of
|
||||||
|
|
||||||
|
CncCat ptyp pde ppr -> do
|
||||||
|
|
||||||
|
pde' <- case (ptyp,pde) of
|
||||||
|
(Yes typ, Yes de) ->
|
||||||
|
liftM yes $ pEval ([(strVar, typeStr)], typ) de
|
||||||
|
(Yes typ, Nope) ->
|
||||||
|
liftM yes $ mkLinDefault gr typ >>= pEval ([(strVar, typeStr)],typ)
|
||||||
|
(May b, Nope) ->
|
||||||
|
return $ May b
|
||||||
|
_ -> return pde -- indirection
|
||||||
|
|
||||||
|
ppr' <- return ppr ----
|
||||||
|
|
||||||
|
return (c, CncCat ptyp pde' ppr')
|
||||||
|
|
||||||
|
CncFun (mt@(Just (_,ty))) pde ppr -> eIn ("linearization in type" +++
|
||||||
|
show ty +++ "of") $ do
|
||||||
|
pde' <- case pde of
|
||||||
|
Yes de -> do
|
||||||
|
liftM yes $ pEval ty de
|
||||||
|
_ -> return pde
|
||||||
|
ppr' <- case ppr of
|
||||||
|
Yes pr -> liftM yes $ comp pr
|
||||||
|
_ -> return ppr
|
||||||
|
return $ (c, CncFun mt pde' ppr') -- only cat in type actually needed
|
||||||
|
|
||||||
|
_ -> return (c,info)
|
||||||
|
where
|
||||||
|
comp = computeConcrete gr
|
||||||
|
pEval = partEval gr
|
||||||
|
eIn cat = errIn ("Error optimizing" +++ cat +++ prt c +++ ":")
|
||||||
|
|
||||||
|
-- the main function for compiling linearizations
|
||||||
|
|
||||||
|
partEval :: SourceGrammar -> (Context,Type) -> Term -> Err Term
|
||||||
|
partEval gr (context, val) trm = do
|
||||||
|
let vars = map fst context
|
||||||
|
args = map Vr vars
|
||||||
|
subst = [(v, Vr v) | v <- vars]
|
||||||
|
trm1 = mkApp trm args
|
||||||
|
trm2 <- etaExpand val trm1
|
||||||
|
trm3 <- comp subst trm2
|
||||||
|
return $ mkAbs vars trm3
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
comp g t = {- refreshTerm t >>= -} computeTerm gr g t
|
||||||
|
|
||||||
|
etaExpand val t = recordExpand val t --- >>= caseEx -- done by comp
|
||||||
|
|
||||||
|
-- here we must be careful not to reduce
|
||||||
|
-- variants {{s = "Auto" ; g = N} ; {s = "Wagen" ; g = M}}
|
||||||
|
-- {s = variants {"Auto" ; "Wagen"} ; g = variants {N ; M}} ;
|
||||||
|
|
||||||
|
recordExpand :: Type -> Term -> Err Term
|
||||||
|
recordExpand typ trm = case unComputed typ of
|
||||||
|
RecType tys -> case trm of
|
||||||
|
FV rs -> return $ FV [R [assign lab (P r lab) | (lab,_) <- tys] | r <- rs]
|
||||||
|
_ -> return $ R [assign lab (P trm lab) | (lab,_) <- tys]
|
||||||
|
_ -> return trm
|
||||||
|
|
||||||
|
|
||||||
|
-- auxiliaries for compiling the resource
|
||||||
|
|
||||||
|
allOperDependencies :: Ident -> BinTree (Ident,Info) -> [(Ident,[Ident])]
|
||||||
|
allOperDependencies m b =
|
||||||
|
[(f, nub (opty pty ++ opty pt)) | (f, ResOper pty pt) <- tree2list b]
|
||||||
|
where
|
||||||
|
opersIn t = case t of
|
||||||
|
Q n c | n == m -> [c]
|
||||||
|
_ -> collectOp opersIn t
|
||||||
|
opty (Yes ty) = opersIn ty
|
||||||
|
opty _ = []
|
||||||
|
|
||||||
|
topoSortOpers :: [(Ident,[Ident])] -> Err [Ident]
|
||||||
|
topoSortOpers st = do
|
||||||
|
let eops = topoTest st
|
||||||
|
either return (\ops -> Bad ("circular operations" +++ unwords (map prt (head ops)))) eops
|
||||||
|
|
||||||
|
mkLinDefault :: SourceGrammar -> Type -> Err Term
|
||||||
|
mkLinDefault gr typ = do
|
||||||
|
case unComputed typ of
|
||||||
|
RecType lts -> mapPairsM mkDefField lts >>= (return . Abs strVar . R . mkAssign)
|
||||||
|
_ -> prtBad "linearization type must be a record type, not" typ
|
||||||
|
where
|
||||||
|
mkDefField typ = case unComputed typ of
|
||||||
|
Table p t -> do
|
||||||
|
t' <- mkDefField t
|
||||||
|
let T _ cs = mkWildCases t'
|
||||||
|
return $ T (TWild p) cs
|
||||||
|
Sort "Str" -> return $ Vr strVar
|
||||||
|
QC q p -> lookupFirstTag gr q p
|
||||||
|
RecType r -> do
|
||||||
|
let (ls,ts) = unzip r
|
||||||
|
ts' <- mapM mkDefField ts
|
||||||
|
return $ R $ [assign l t | (l,t) <- zip ls ts']
|
||||||
|
_ -> prtBad "linearization type field cannot be" typ
|
||||||
|
|
||||||
58
src/GF/Compile/PGrammar.hs
Normal file
58
src/GF/Compile/PGrammar.hs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
module PGrammar where
|
||||||
|
|
||||||
|
---import LexGF
|
||||||
|
import ParGF
|
||||||
|
import SourceToGrammar
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import qualified AbsGFC as A
|
||||||
|
import qualified GFC as G
|
||||||
|
import GetGrammar
|
||||||
|
import Macros
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
pTerm :: String -> Err Term
|
||||||
|
pTerm s = do
|
||||||
|
e <- err2err $ pExp $ myLexer s
|
||||||
|
transExp e
|
||||||
|
|
||||||
|
pTrm :: String -> Term
|
||||||
|
pTrm = errVal (vr (zIdent "x")) . pTerm ---
|
||||||
|
|
||||||
|
pTrms :: String -> [Term]
|
||||||
|
pTrms = map pTrm . sep [] where
|
||||||
|
sep t cs = case cs of
|
||||||
|
',' : cs2 -> reverse t : sep [] cs2
|
||||||
|
c : cs2 -> sep (c:t) cs2
|
||||||
|
_ -> [reverse t]
|
||||||
|
|
||||||
|
pTrm' :: String -> [Term]
|
||||||
|
pTrm' = err (const []) singleton . pTerm
|
||||||
|
|
||||||
|
pMeta :: String -> Integer
|
||||||
|
pMeta _ = 0 ---
|
||||||
|
|
||||||
|
pzIdent :: String -> Ident
|
||||||
|
pzIdent = zIdent
|
||||||
|
|
||||||
|
{-
|
||||||
|
string2formsAndTerm :: String -> ([Term],Term)
|
||||||
|
string2formsAndTerm s = case s of
|
||||||
|
'[':_:_ -> case span (/=']') s of
|
||||||
|
(x,_:y) -> (pTrms (tail x), pTrm y)
|
||||||
|
_ -> ([],pTrm s)
|
||||||
|
_ -> ([], pTrm s)
|
||||||
|
|
||||||
|
string2ident :: String -> Err Ident
|
||||||
|
string2ident s = return $ case s of
|
||||||
|
c:'_':i -> identV (readIntArg i,[c]) ---
|
||||||
|
_ -> zIdent s
|
||||||
|
|
||||||
|
-- reads the Haskell datatype
|
||||||
|
readGrammar :: String -> Err GrammarST
|
||||||
|
readGrammar s = case [x | (x,t) <- reads s, ("","") <- lex t] of
|
||||||
|
[x] -> return x
|
||||||
|
[] -> Bad "no parse of Grammar"
|
||||||
|
_ -> Bad "ambiguous parse of Grammar"
|
||||||
|
-}
|
||||||
69
src/GF/Compile/PrOld.hs
Normal file
69
src/GF/Compile/PrOld.hs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
module PrOld where
|
||||||
|
|
||||||
|
import PrGrammar
|
||||||
|
import CanonToGrammar
|
||||||
|
import qualified GFC
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Macros
|
||||||
|
import Modules
|
||||||
|
import qualified PrintGF as P
|
||||||
|
import GrammarToSource
|
||||||
|
|
||||||
|
import List
|
||||||
|
import Operations
|
||||||
|
import UseIO
|
||||||
|
|
||||||
|
-- a hack to print gf2 into gf1 readable files
|
||||||
|
-- Works only for canonical grammars, printed into GFC. Otherwise we would have
|
||||||
|
-- problems with qualified names.
|
||||||
|
--- printnames are not preserved, nor are lindefs
|
||||||
|
|
||||||
|
printGrammarOld :: GFC.CanonGrammar -> String
|
||||||
|
printGrammarOld gr = err id id $ do
|
||||||
|
as0 <- mapM canon2sourceModule [im | im@(_,ModMod m) <- modules gr, isModAbs m]
|
||||||
|
cs0 <- mapM canon2sourceModule
|
||||||
|
[im | im@(_,ModMod m) <- modules gr, isModCnc m || isModRes m]
|
||||||
|
as1 <- return $ concatMap stripInfo $ concatMap (tree2list . js . snd) as0
|
||||||
|
cs1 <- return $ concatMap stripInfo $ concatMap (tree2list . js . snd) cs0
|
||||||
|
return $ unlines $ map prj $ srt as1 ++ srt cs1
|
||||||
|
where
|
||||||
|
js (ModMod m) = jments m
|
||||||
|
srt = sortBy (\ (i,_) (j,_) -> compare i j)
|
||||||
|
prj ii = P.printTree $ trAnyDef ii
|
||||||
|
|
||||||
|
stripInfo :: (Ident,Info) -> [(Ident,Info)]
|
||||||
|
stripInfo (c,i) = case i of
|
||||||
|
AbsCat (Yes co) (Yes fs) -> rc $ AbsCat (Yes (stripContext co)) nope
|
||||||
|
AbsFun (Yes ty) (Yes tr) -> rc $ AbsFun (Yes (stripTerm ty)) (Yes(stripTerm tr))
|
||||||
|
AbsFun (Yes ty) _ -> rc $ AbsFun (Yes (stripTerm ty)) nope
|
||||||
|
ResParam (Yes ps) -> rc $ ResParam (Yes [(c,stripContext co) | (c,co)<- ps])
|
||||||
|
CncCat (Yes ty) _ _ -> rc $
|
||||||
|
CncCat (Yes (stripTerm ty)) nope nope
|
||||||
|
CncFun _ (Yes tr) _ -> rc $ CncFun Nothing (Yes (stripTerm tr)) nope
|
||||||
|
_ -> []
|
||||||
|
where
|
||||||
|
rc j = [(c,j)]
|
||||||
|
|
||||||
|
stripContext co = [(x, stripTerm t) | (x,t) <- co]
|
||||||
|
|
||||||
|
stripTerm t = case t of
|
||||||
|
Q _ c -> Vr c
|
||||||
|
QC _ c -> Vr c
|
||||||
|
T ti cs -> T ti' [(stripPattern p, stripTerm c) | (p,c) <- cs] where
|
||||||
|
ti' = case ti of
|
||||||
|
TTyped ty -> TTyped $ stripTerm ty
|
||||||
|
TComp ty -> TComp $ stripTerm ty
|
||||||
|
TWild ty -> TWild $ stripTerm ty
|
||||||
|
_ -> ti
|
||||||
|
_ -> composSafeOp stripTerm t
|
||||||
|
|
||||||
|
stripPattern p = case p of
|
||||||
|
PC c [] -> PV c
|
||||||
|
PP _ c [] -> PV c
|
||||||
|
PC c ps -> PC c (map stripPattern ps)
|
||||||
|
PP _ c ps -> PC c (map stripPattern ps)
|
||||||
|
PR lps -> PR [(l, stripPattern p) | (l,p) <- lps]
|
||||||
|
PT t p -> PT (stripTerm t) (stripPattern p)
|
||||||
|
_ -> p
|
||||||
|
|
||||||
51
src/GF/Compile/RemoveLiT.hs
Normal file
51
src/GF/Compile/RemoveLiT.hs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
module RemoveLiT (removeLiT) where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Modules
|
||||||
|
import Macros
|
||||||
|
import Lookup
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- remove obsolete (Lin C) expressions before doing anything else. AR 21/6/2003
|
||||||
|
|
||||||
|
-- What the program does is replace the occurrences of Lin C with the actual
|
||||||
|
-- definition T given in lincat C = T ; with {s : Str} if no lincat is found.
|
||||||
|
-- The procedule is uncertain, if T contains another Lin.
|
||||||
|
|
||||||
|
removeLiT :: SourceGrammar -> Err SourceGrammar
|
||||||
|
removeLiT gr = liftM MGrammar $ mapM (remlModule gr) (modules gr)
|
||||||
|
|
||||||
|
remlModule :: SourceGrammar -> (Ident,SourceModInfo) -> Err (Ident,SourceModInfo)
|
||||||
|
remlModule gr mi@(name,mod) = case mod of
|
||||||
|
ModMod (Module mt fs me ops js) -> do
|
||||||
|
js1 <- mapMTree (remlResInfo gr) js
|
||||||
|
let mod2 = ModMod $ Module mt fs me ops js1
|
||||||
|
return $ (name,mod2)
|
||||||
|
_ -> return mi
|
||||||
|
|
||||||
|
remlResInfo :: SourceGrammar -> (Ident,Info) -> Err (Ident,Info)
|
||||||
|
remlResInfo gr mi@(i,info) = case info of
|
||||||
|
ResOper pty ptr -> liftM ((,) i) $ liftM2 ResOper (ren pty) (ren ptr)
|
||||||
|
CncCat pty ptr ppr -> liftM ((,) i) $ liftM3 CncCat (ren pty) (ren ptr) (ren ppr)
|
||||||
|
CncFun mt ptr ppr -> liftM ((,) i) $ liftM2 (CncFun mt) (ren ptr) (ren ppr)
|
||||||
|
_ -> return mi
|
||||||
|
where
|
||||||
|
ren = remlPerh gr
|
||||||
|
|
||||||
|
remlPerh gr pt = case pt of
|
||||||
|
Yes t -> liftM Yes $ remlTerm gr t
|
||||||
|
_ -> return pt
|
||||||
|
|
||||||
|
remlTerm :: SourceGrammar -> Term -> Err Term
|
||||||
|
remlTerm gr trm = case trm of
|
||||||
|
LiT c -> look c >>= remlTerm gr
|
||||||
|
_ -> composOp (remlTerm gr) trm
|
||||||
|
where
|
||||||
|
look c = err (const $ return defLinType) return $ lookupLincat gr m c
|
||||||
|
m = case [cnc | (cnc,ModMod m) <- modules gr, isModCnc m] of
|
||||||
|
cnc:_ -> cnc -- actually there is always exactly one
|
||||||
|
_ -> zIdent "CNC"
|
||||||
263
src/GF/Compile/Rename.hs
Normal file
263
src/GF/Compile/Rename.hs
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
module Rename where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Modules
|
||||||
|
import Ident
|
||||||
|
import Macros
|
||||||
|
import PrGrammar
|
||||||
|
import Lookup
|
||||||
|
import Extend
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- AR 14/5/2003
|
||||||
|
|
||||||
|
-- The top-level function $renameGrammar$ does several things:
|
||||||
|
-- * extends each module symbol table by indirections to extended module
|
||||||
|
-- * changes unqualified and as-qualified imports to absolutely qualified
|
||||||
|
-- * goes through the definitions and resolves names
|
||||||
|
-- Dependency analysis between modules has been performed before this pass.
|
||||||
|
-- Hence we can proceed by $fold$ing 'from left to right'.
|
||||||
|
|
||||||
|
renameGrammar :: SourceGrammar -> Err SourceGrammar
|
||||||
|
renameGrammar g = liftM (MGrammar . reverse) $ foldM renameModule [] (modules g)
|
||||||
|
|
||||||
|
-- this gives top-level access to renaming term input in the cc command
|
||||||
|
renameSourceTerm :: SourceGrammar -> Ident -> Term -> Err Term
|
||||||
|
renameSourceTerm g m t = do
|
||||||
|
mo <- lookupErr m (modules g)
|
||||||
|
status <- buildStatus g m mo
|
||||||
|
renameTerm status [] t
|
||||||
|
|
||||||
|
renameModule :: [SourceModule] -> SourceModule -> Err [SourceModule]
|
||||||
|
renameModule ms (name,mod) = errIn ("renaming module" +++ prt name) $ case mod of
|
||||||
|
ModMod (Module mt fs me ops js) -> do
|
||||||
|
(_,mod1@(ModMod m)) <- extendModule ms (name,mod)
|
||||||
|
let js1 = jments m
|
||||||
|
status <- buildStatus (MGrammar ms) name mod1
|
||||||
|
js2 <- mapMTree (renameInfo status) js1
|
||||||
|
let mod2 = ModMod $ Module mt fs me (map forceQualif ops) js2
|
||||||
|
return $ (name,mod2) : ms
|
||||||
|
|
||||||
|
extendModule :: [SourceModule] -> SourceModule -> Err SourceModule
|
||||||
|
extendModule ms (name,mod) = case mod of
|
||||||
|
ModMod (Module mt fs me ops js0) -> do
|
||||||
|
js <- case mt of
|
||||||
|
{- --- building the {s : Str} lincat
|
||||||
|
MTConcrete a -> do
|
||||||
|
ModMod ma <- lookupModule (MGrammar ms) a
|
||||||
|
let cats = [c | (c,AbsCat _ _) <- tree2list $ jments ma]
|
||||||
|
jscs = [(c,CncCat (yes defLinType) nope nope) | c <- cats]
|
||||||
|
return $ updatesTreeNondestr jscs js0
|
||||||
|
-}
|
||||||
|
_ -> return js0
|
||||||
|
js1 <- case me of
|
||||||
|
Just n -> do
|
||||||
|
m0 <- case lookup n ms of
|
||||||
|
Just (ModMod m) -> do
|
||||||
|
testErr (sameMType (mtype m) mt)
|
||||||
|
("illegal extension type to module" +++ prt name)
|
||||||
|
return m
|
||||||
|
_ -> Bad $ "cannot find extended module" +++ prt n
|
||||||
|
extendMod n (jments m0) js
|
||||||
|
_ -> return js
|
||||||
|
return $ (name,ModMod (Module mt fs Nothing ops js1))
|
||||||
|
|
||||||
|
|
||||||
|
type Status = (StatusTree, [(OpenSpec Ident, StatusTree)])
|
||||||
|
|
||||||
|
type StatusTree = BinTree (Ident,StatusInfo)
|
||||||
|
|
||||||
|
type StatusInfo = Ident -> Term
|
||||||
|
|
||||||
|
renameIdentTerm :: Status -> Term -> Err Term
|
||||||
|
renameIdentTerm env@(act,imps) t = case t of
|
||||||
|
Vr c -> do
|
||||||
|
f <- lookupTreeMany prt opens c
|
||||||
|
return $ f c
|
||||||
|
Cn c -> do
|
||||||
|
f <- lookupTreeMany prt opens c
|
||||||
|
return $ f c
|
||||||
|
Q m' c -> do
|
||||||
|
m <- lookupErr m' qualifs
|
||||||
|
f <- lookupTree prt c m
|
||||||
|
return $ f c
|
||||||
|
QC m' c -> do
|
||||||
|
m <- lookupErr m' qualifs
|
||||||
|
f <- lookupTree prt c m
|
||||||
|
return $ f c
|
||||||
|
_ -> return t
|
||||||
|
where
|
||||||
|
opens = act : [st | (OSimple _,st) <- imps]
|
||||||
|
qualifs = [ (m, st) | (OQualif m _, st) <- imps]
|
||||||
|
|
||||||
|
--- would it make sense to optimize this by inlining?
|
||||||
|
renameIdentPatt :: Status -> Patt -> Err Patt
|
||||||
|
renameIdentPatt env p = do
|
||||||
|
let t = patt2term p
|
||||||
|
t' <- renameIdentTerm env t
|
||||||
|
term2patt t'
|
||||||
|
|
||||||
|
info2status :: Maybe Ident -> (Ident,Info) -> (Ident,StatusInfo)
|
||||||
|
info2status mq (c,i) = (c, case i of
|
||||||
|
AbsFun _ (Yes (Con g)) | g == c -> maybe Con QC mq
|
||||||
|
ResValue _ -> maybe Con QC mq
|
||||||
|
ResParam _ -> maybe Con QC mq
|
||||||
|
AnyInd True m -> maybe Con (const (QC m)) mq
|
||||||
|
AnyInd False m -> maybe Cn (const (Q m)) mq
|
||||||
|
_ -> maybe Cn Q mq
|
||||||
|
)
|
||||||
|
|
||||||
|
tree2status :: OpenSpec Ident -> BinTree (Ident,Info) -> BinTree (Ident,StatusInfo)
|
||||||
|
tree2status o = case o of
|
||||||
|
OSimple i -> mapTree (info2status (Just i))
|
||||||
|
OQualif i j -> mapTree (info2status (Just j))
|
||||||
|
|
||||||
|
buildStatus :: SourceGrammar -> Ident -> SourceModInfo -> Err Status
|
||||||
|
buildStatus gr c mo = let mo' = self2status c mo in case mo of
|
||||||
|
ModMod m -> do
|
||||||
|
let ops = opens m
|
||||||
|
mods <- mapM (lookupModule gr . openedModule) ops
|
||||||
|
let sts = map modInfo2status $ zip ops mods
|
||||||
|
return $ if isModCnc m
|
||||||
|
then (NT, sts) -- the module itself does not define any names
|
||||||
|
else (mo',sts) -- so the empty ident is not needed
|
||||||
|
|
||||||
|
modInfo2status :: (OpenSpec Ident,SourceModInfo) -> (OpenSpec Ident, StatusTree)
|
||||||
|
modInfo2status (o,i) = (o,case i of
|
||||||
|
ModMod m -> tree2status o (jments m)
|
||||||
|
)
|
||||||
|
|
||||||
|
self2status :: Ident -> SourceModInfo -> StatusTree
|
||||||
|
self2status c i = case i of
|
||||||
|
ModMod m -> mapTree (info2status (Just c)) (jments m) -- qualify internal
|
||||||
|
--- ModMod m -> mapTree (resInfo2status Nothing) (jments m)
|
||||||
|
-- change Lookup.qualifAnnot if you change this
|
||||||
|
|
||||||
|
forceQualif o = case o of
|
||||||
|
OSimple i -> OQualif i i
|
||||||
|
OQualif _ i -> OQualif i i
|
||||||
|
|
||||||
|
renameInfo :: Status -> (Ident,Info) -> Err (Ident,Info)
|
||||||
|
renameInfo status (i,info) = errIn ("renaming definition of" +++ prt i) $
|
||||||
|
liftM ((,) i) $ case info of
|
||||||
|
AbsCat pco pfs -> liftM2 AbsCat (renPerh (renameContext status) pco)
|
||||||
|
(return pfs) ----
|
||||||
|
AbsFun pty ptr -> liftM2 AbsFun (ren pty) (ren ptr)
|
||||||
|
|
||||||
|
ResOper pty ptr -> liftM2 ResOper (ren pty) (ren ptr)
|
||||||
|
ResParam pp -> liftM ResParam (renPerh (mapM (renameParam status)) pp)
|
||||||
|
ResValue t -> liftM ResValue (ren t)
|
||||||
|
CncCat pty ptr ppr -> liftM3 CncCat (ren pty) (ren ptr) (ren ppr)
|
||||||
|
CncFun mt ptr ppr -> liftM2 (CncFun mt) (ren ptr) (ren ppr)
|
||||||
|
_ -> return info
|
||||||
|
where
|
||||||
|
ren = renPerh rent
|
||||||
|
rent = renameTerm status []
|
||||||
|
|
||||||
|
renPerh ren pt = case pt of
|
||||||
|
Yes t -> liftM Yes $ ren t
|
||||||
|
_ -> return pt
|
||||||
|
|
||||||
|
renameTerm :: Status -> [Ident] -> Term -> Err Term
|
||||||
|
renameTerm env vars = ren vars where
|
||||||
|
ren vs trm = case trm of
|
||||||
|
Abs x b -> liftM (Abs x) (ren (x:vs) b)
|
||||||
|
Prod x a b -> liftM2 (Prod x) (ren vs a) (ren (x:vs) b)
|
||||||
|
Vr x
|
||||||
|
| elem x vs -> return trm
|
||||||
|
| otherwise -> renid trm
|
||||||
|
Cn _ -> renid trm
|
||||||
|
Con _ -> renid trm
|
||||||
|
Q _ _ -> renid trm
|
||||||
|
QC _ _ -> renid trm
|
||||||
|
|
||||||
|
---- Eqs eqs -> Eqs (map (renameEquation consts vs) eqs)
|
||||||
|
T i cs -> do
|
||||||
|
i' <- case i of
|
||||||
|
TTyped ty -> liftM TTyped $ ren vs ty -- the only annotation in source
|
||||||
|
_ -> return i
|
||||||
|
liftM (T i') $ mapM (renCase vs) cs
|
||||||
|
|
||||||
|
Let (x,(m,a)) b -> do
|
||||||
|
m' <- case m of
|
||||||
|
Just ty -> liftM Just $ ren vs ty
|
||||||
|
_ -> return m
|
||||||
|
a' <- ren vs a
|
||||||
|
b' <- ren (x:vs) b
|
||||||
|
return $ Let (x,(m',a')) b'
|
||||||
|
|
||||||
|
P t@(Vr r) l -- for constant t we know it is projection
|
||||||
|
| elem r vs -> return trm -- var proj first
|
||||||
|
| otherwise -> case renid (Q r (label2ident l)) of -- qualif second
|
||||||
|
Ok t -> return t
|
||||||
|
_ -> liftM (flip P l) $ renid t -- const proj last
|
||||||
|
|
||||||
|
_ -> composOp (ren vs) trm
|
||||||
|
|
||||||
|
renid = renameIdentTerm env
|
||||||
|
renCase vs (p,t) = do
|
||||||
|
(p',vs') <- renpatt p
|
||||||
|
t' <- ren (vs' ++ vs) t
|
||||||
|
return (p',t')
|
||||||
|
renpatt = renamePattern env
|
||||||
|
|
||||||
|
-- vars not needed in env, since patterns always overshadow old vars
|
||||||
|
|
||||||
|
renamePattern :: Status -> Patt -> Err (Patt,[Ident])
|
||||||
|
renamePattern env patt = case patt of
|
||||||
|
|
||||||
|
PC c ps -> do
|
||||||
|
c' <- renameIdentTerm env $ Cn c
|
||||||
|
psvss <- mapM renp ps
|
||||||
|
let (ps',vs) = unzip psvss
|
||||||
|
return $ case c' of
|
||||||
|
QC p d -> (PP p d ps', concat vs)
|
||||||
|
_ -> (PC c ps', concat vs)
|
||||||
|
|
||||||
|
---- PP p c ps -> (PP p c ps',concat vs') where (ps',vs') = unzip $ map renp ps
|
||||||
|
|
||||||
|
PV x -> case renid patt of
|
||||||
|
Ok p -> return (p,[])
|
||||||
|
_ -> return (patt, [x])
|
||||||
|
|
||||||
|
PR r -> do
|
||||||
|
let (ls,ps) = unzip r
|
||||||
|
psvss <- mapM renp ps
|
||||||
|
let (ps',vs') = unzip psvss
|
||||||
|
return (PR (zip ls ps'), concat vs')
|
||||||
|
|
||||||
|
_ -> return (patt,[])
|
||||||
|
|
||||||
|
where
|
||||||
|
renp = renamePattern env
|
||||||
|
renid = renameIdentPatt env
|
||||||
|
|
||||||
|
renameParam :: Status -> (Ident, Context) -> Err (Ident, Context)
|
||||||
|
renameParam env (c,co) = do
|
||||||
|
co' <- renameContext env co
|
||||||
|
return (c,co')
|
||||||
|
|
||||||
|
renameContext :: Status -> Context -> Err Context
|
||||||
|
renameContext b = renc [] where
|
||||||
|
renc vs cont = case cont of
|
||||||
|
(x,t) : xts
|
||||||
|
| isWildIdent x -> do
|
||||||
|
t' <- ren vs t
|
||||||
|
xts' <- renc vs xts
|
||||||
|
return $ (x,t') : xts'
|
||||||
|
| otherwise -> do
|
||||||
|
t' <- ren vs t
|
||||||
|
let vs' = x:vs
|
||||||
|
xts' <- renc vs' xts
|
||||||
|
return $ (x,t') : xts'
|
||||||
|
_ -> return cont
|
||||||
|
ren = renameTerm b
|
||||||
|
|
||||||
|
{-
|
||||||
|
renameEquation :: Status -> [Ident] -> Equation -> Equation
|
||||||
|
renameEquation b vs (ps,t) = (ps',renameTerm b (concat vs' ++ vs) t) where
|
||||||
|
(ps',vs') = unzip $ map (renamePattern b vs) ps
|
||||||
|
-}
|
||||||
|
|
||||||
338
src/GF/Compile/ShellState.hs
Normal file
338
src/GF/Compile/ShellState.hs
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
module ShellState where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import GFC
|
||||||
|
import AbsGFC
|
||||||
|
---import CMacros
|
||||||
|
import Look
|
||||||
|
import qualified Modules as M
|
||||||
|
import qualified Grammar as G
|
||||||
|
import qualified PrGrammar as P
|
||||||
|
import CF
|
||||||
|
import CFIdent
|
||||||
|
import CanonToCF
|
||||||
|
import Morphology
|
||||||
|
import Option
|
||||||
|
import Ident
|
||||||
|
import Arch (ModTime)
|
||||||
|
|
||||||
|
-- AR 11/11/2001 -- 17/6/2003 (for modules) ---- unfinished
|
||||||
|
|
||||||
|
-- multilingual state with grammars and options
|
||||||
|
data ShellState = ShSt {
|
||||||
|
abstract :: Maybe Ident , -- pointer to actual abstract; nothing in empty st
|
||||||
|
concrete :: Maybe Ident , -- pointer to primary concrete
|
||||||
|
concretes :: [(Ident,Ident)], -- list of all concretes
|
||||||
|
canModules :: CanonGrammar , -- the place where abstracts and concretes reside
|
||||||
|
srcModules :: G.SourceGrammar , -- the place of saved resource modules
|
||||||
|
cfs :: [(Ident,CF)] , -- context-free grammars
|
||||||
|
morphos :: [(Ident,Morpho)], -- morphologies
|
||||||
|
gloptions :: Options, -- global options
|
||||||
|
readFiles :: [(FilePath,ModTime)],-- files read
|
||||||
|
absCats :: [(G.Cat,(G.Context, -- cats, their contexts,
|
||||||
|
[(G.Fun,G.Type)], -- functions to them,
|
||||||
|
[((G.Fun,Int),G.Type)]))], -- functions on them
|
||||||
|
statistics :: [Statistics] -- statistics on grammars
|
||||||
|
}
|
||||||
|
|
||||||
|
data Statistics =
|
||||||
|
StDepTypes Bool -- whether there are dependent types
|
||||||
|
| StBoundVars [G.Cat] -- which categories have bound variables
|
||||||
|
--- -- etc
|
||||||
|
deriving (Eq,Ord)
|
||||||
|
|
||||||
|
emptyShellState = ShSt {
|
||||||
|
abstract = Nothing,
|
||||||
|
concrete = Nothing,
|
||||||
|
concretes = [],
|
||||||
|
canModules = M.emptyMGrammar,
|
||||||
|
srcModules = M.emptyMGrammar,
|
||||||
|
cfs = [],
|
||||||
|
morphos = [],
|
||||||
|
gloptions = noOptions,
|
||||||
|
readFiles = [],
|
||||||
|
absCats = [],
|
||||||
|
statistics = []
|
||||||
|
}
|
||||||
|
|
||||||
|
type Language = Ident
|
||||||
|
language = identC
|
||||||
|
prLanguage = prIdent
|
||||||
|
|
||||||
|
-- grammar for one language in a state, comprising its abs and cnc
|
||||||
|
|
||||||
|
data StateGrammar = StGr {
|
||||||
|
absId :: Ident,
|
||||||
|
cncId :: Ident,
|
||||||
|
grammar :: CanonGrammar,
|
||||||
|
cf :: CF,
|
||||||
|
morpho :: Morpho
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyStateGrammar = StGr {
|
||||||
|
absId = identC "#EMPTY", ---
|
||||||
|
cncId = identC "#EMPTY", ---
|
||||||
|
grammar = M.emptyMGrammar,
|
||||||
|
cf = emptyCF,
|
||||||
|
morpho = emptyMorpho
|
||||||
|
}
|
||||||
|
|
||||||
|
-- analysing shell grammar into parts
|
||||||
|
stateGrammarST = grammar
|
||||||
|
stateCF = cf
|
||||||
|
stateMorpho = morpho
|
||||||
|
stateOptions _ = noOptions ----
|
||||||
|
|
||||||
|
cncModuleIdST = stateGrammarST
|
||||||
|
|
||||||
|
-- form a shell state from a canonical grammar
|
||||||
|
|
||||||
|
grammar2shellState :: Options -> (CanonGrammar, G.SourceGrammar) -> Err ShellState
|
||||||
|
grammar2shellState opts (gr,sgr) = updateShellState opts emptyShellState (gr,(sgr,[]))
|
||||||
|
|
||||||
|
-- update a shell state from a canonical grammar
|
||||||
|
|
||||||
|
updateShellState :: Options -> ShellState ->
|
||||||
|
(CanonGrammar,(G.SourceGrammar,[(FilePath,ModTime)])) ->
|
||||||
|
Err ShellState
|
||||||
|
updateShellState opts sh (gr,(sgr,rts)) = do
|
||||||
|
let cgr = M.updateMGrammar (canModules sh) gr
|
||||||
|
a' = ifNull Nothing (return . last) $ allAbstracts cgr
|
||||||
|
abstr0 <- case abstract sh of
|
||||||
|
Just a -> do
|
||||||
|
--- test that abstract is compatible
|
||||||
|
return $ Just a
|
||||||
|
_ -> return a'
|
||||||
|
let concrs = maybe [] (allConcretes cgr) abstr0
|
||||||
|
concr0 = ifNull Nothing (return . last) concrs
|
||||||
|
notInrts f = notElem f $ map fst rts
|
||||||
|
cfs <- mapM (canon2cf opts cgr) concrs --- would not need to update all...
|
||||||
|
|
||||||
|
let funs = [] ---- funRulesOf cgr
|
||||||
|
let cats = [] ---- allCatsOf cgr
|
||||||
|
let csi = [] ----
|
||||||
|
{-
|
||||||
|
[(c,(co,
|
||||||
|
[(fun,typ) | (fun,typ) <- funs, compatType tc typ],
|
||||||
|
funsOnTypeFs compatType funs tc))
|
||||||
|
| (c,co) <- cats, let tc = cat2type c]
|
||||||
|
-}
|
||||||
|
let deps = True ---- not $ null $ allDepCats cgr
|
||||||
|
let binds = [] ---- allCatsWithBind cgr
|
||||||
|
|
||||||
|
return $ ShSt {
|
||||||
|
abstract = abstr0,
|
||||||
|
concrete = concr0,
|
||||||
|
concretes = zip concrs concrs,
|
||||||
|
canModules = cgr,
|
||||||
|
srcModules = M.updateMGrammar (srcModules sh) sgr,
|
||||||
|
cfs = zip concrs cfs,
|
||||||
|
morphos = zip concrs (repeat emptyMorpho),
|
||||||
|
gloptions = opts, ---- -- global options
|
||||||
|
readFiles = [ft | ft@(f,_) <- readFiles sh, notInrts f] ++ rts,
|
||||||
|
absCats = csi,
|
||||||
|
statistics = [StDepTypes deps,StBoundVars binds]
|
||||||
|
}
|
||||||
|
|
||||||
|
prShellStateInfo :: ShellState -> String
|
||||||
|
prShellStateInfo sh = unlines [
|
||||||
|
"main abstract : " +++ maybe "(none)" P.prt (abstract sh),
|
||||||
|
"main concrete : " +++ maybe "(none)" P.prt (concrete sh),
|
||||||
|
"all concretes : " +++ unwords (map (P.prt . fst) (concretes sh)),
|
||||||
|
"canonical modules :" +++ unwords (map (P.prt .fst) (M.modules (canModules sh))),
|
||||||
|
"source modules : " +++ unwords (map (P.prt .fst) (M.modules (srcModules sh))),
|
||||||
|
"global options : " +++ prOpts (gloptions sh)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
-- form just one state grammar, if unique, from a canonical grammar
|
||||||
|
|
||||||
|
grammar2stateGrammar :: Options -> CanonGrammar -> Err StateGrammar
|
||||||
|
grammar2stateGrammar opts gr = do
|
||||||
|
st <- grammar2shellState opts (gr,M.emptyMGrammar)
|
||||||
|
concr <- maybeErr "no concrete syntax" $ concrete st
|
||||||
|
return $ stateGrammarOfLang st concr
|
||||||
|
|
||||||
|
-- all abstract modules
|
||||||
|
allAbstracts :: CanonGrammar -> [Ident]
|
||||||
|
allAbstracts gr = [i | (i,M.ModMod m) <- M.modules gr, M.mtype m == M.MTAbstract]
|
||||||
|
|
||||||
|
-- the last abstract in dependency order
|
||||||
|
greatestAbstract :: CanonGrammar -> Maybe Ident
|
||||||
|
greatestAbstract gr = case allAbstracts gr of
|
||||||
|
[] -> Nothing
|
||||||
|
a -> return $ last a
|
||||||
|
|
||||||
|
-- all concretes for a given abstract
|
||||||
|
allConcretes :: CanonGrammar -> Ident -> [Ident]
|
||||||
|
allConcretes gr a = [i | (i,M.ModMod m) <- M.modules gr, M.mtype m== M.MTConcrete a]
|
||||||
|
|
||||||
|
stateGrammarOfLang :: ShellState -> Language -> StateGrammar
|
||||||
|
stateGrammarOfLang st l = StGr {
|
||||||
|
absId = maybe (identC "Abs") id (abstract st), ---
|
||||||
|
cncId = l,
|
||||||
|
grammar = canModules st, ---- only those needed for l
|
||||||
|
cf = maybe emptyCF id (lookup l (cfs st)),
|
||||||
|
morpho = maybe emptyMorpho id (lookup l (morphos st))
|
||||||
|
}
|
||||||
|
|
||||||
|
grammarOfLang st = stateGrammarST . stateGrammarOfLang st
|
||||||
|
cfOfLang st = stateCF . stateGrammarOfLang st
|
||||||
|
morphoOfLang st = stateMorpho . stateGrammarOfLang st
|
||||||
|
optionsOfLang st = stateOptions . stateGrammarOfLang st
|
||||||
|
|
||||||
|
-- the last introduced grammar, stored in options, is the default for operations
|
||||||
|
|
||||||
|
firstStateGrammar :: ShellState -> StateGrammar
|
||||||
|
firstStateGrammar st = errVal emptyStateGrammar $ do
|
||||||
|
concr <- maybeErr "no concrete syntax" $ concrete st
|
||||||
|
return $ stateGrammarOfLang st concr
|
||||||
|
|
||||||
|
mkStateGrammar :: ShellState -> Language -> StateGrammar
|
||||||
|
mkStateGrammar = stateGrammarOfLang
|
||||||
|
|
||||||
|
-- analysing shell state into parts
|
||||||
|
globalOptions = gloptions
|
||||||
|
allLanguages = map fst . concretes
|
||||||
|
|
||||||
|
allStateGrammars = map snd . allStateGrammarsWithNames
|
||||||
|
|
||||||
|
allStateGrammarsWithNames st = [(c, mkStateGrammar st c) | (c,_) <- concretes st]
|
||||||
|
|
||||||
|
allGrammarFileNames st = [prLanguage c ++ ".gf" | (c,_) <- concretes st] ---
|
||||||
|
|
||||||
|
{-
|
||||||
|
allActiveStateGrammarsWithNames (ShSt (ma,gs,_)) =
|
||||||
|
[(l, mkStateGrammar a c) | (l,((_,True),c)) <- gs, Just a <- [ma]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
allActiveGrammars = map snd . allActiveStateGrammarsWithNames
|
||||||
|
|
||||||
|
allGrammarSTs = map stateGrammarST . allStateGrammars
|
||||||
|
allCFs = map stateCF . allStateGrammars
|
||||||
|
|
||||||
|
firstGrammarST = stateGrammarST . firstStateGrammar
|
||||||
|
firstAbstractST = abstractOf . firstGrammarST
|
||||||
|
firstConcreteST = concreteOf . firstGrammarST
|
||||||
|
-}
|
||||||
|
-- command-line option -language=foo overrides the actual grammar in state
|
||||||
|
grammarOfOptState :: Options -> ShellState -> StateGrammar
|
||||||
|
grammarOfOptState opts st =
|
||||||
|
maybe (firstStateGrammar st) (stateGrammarOfLang st . language) $
|
||||||
|
getOptVal opts useLanguage
|
||||||
|
|
||||||
|
-- command-line option -cat=foo overrides the possible start cat of a grammar
|
||||||
|
firstCatOpts :: Options -> StateGrammar -> CFCat
|
||||||
|
firstCatOpts opts sgr =
|
||||||
|
maybe (stateFirstCat sgr) (string2CFCat (P.prt (absId sgr))) $
|
||||||
|
getOptVal opts firstCat
|
||||||
|
|
||||||
|
-- a grammar can have start category as option startcat=foo ; default is S
|
||||||
|
stateFirstCat sgr =
|
||||||
|
maybe (string2CFCat a "S") (string2CFCat a) $
|
||||||
|
getOptVal (stateOptions sgr) gStartCat
|
||||||
|
where
|
||||||
|
a = P.prt (absId sgr)
|
||||||
|
|
||||||
|
-- the first cat for random generation
|
||||||
|
firstAbsCat :: Options -> StateGrammar -> G.QIdent
|
||||||
|
firstAbsCat opts sgr =
|
||||||
|
maybe (absId sgr, identC "S") (\c -> (absId sgr, identC c)) $ ----
|
||||||
|
getOptVal opts firstCat
|
||||||
|
|
||||||
|
{-
|
||||||
|
-- command-line option -cat=foo overrides the possible start cat of a grammar
|
||||||
|
stateTransferFun :: StateGrammar -> Maybe Fun
|
||||||
|
stateTransferFun sgr = getOptVal (stateOptions sgr) transferFun >>= return . zIdent
|
||||||
|
|
||||||
|
stateConcrete = concreteOf . stateGrammarST
|
||||||
|
stateAbstract = abstractOf . stateGrammarST
|
||||||
|
|
||||||
|
maybeStateAbstract (ShSt (ma,_,_)) = ma
|
||||||
|
hasStateAbstract = maybe False (const True) . maybeStateAbstract
|
||||||
|
abstractOfState = maybe emptyAbstractST id . maybeStateAbstract
|
||||||
|
|
||||||
|
stateIsWord sg = isKnownWord (stateMorpho sg)
|
||||||
|
|
||||||
|
|
||||||
|
-- getting info on a language
|
||||||
|
existLang :: ShellState -> Language -> Bool
|
||||||
|
existLang st lang = elem lang (allLanguages st)
|
||||||
|
|
||||||
|
stateConcreteOfLang :: ShellState -> Language -> StateConcrete
|
||||||
|
stateConcreteOfLang (ShSt (_,gs,_)) lang =
|
||||||
|
maybe emptyStateConcrete snd $ lookup lang gs
|
||||||
|
|
||||||
|
fileOfLang :: ShellState -> Language -> FilePath
|
||||||
|
fileOfLang (ShSt (_,gs,_)) lang =
|
||||||
|
maybe nonExistingLangFile (fst .fst) $ lookup lang gs
|
||||||
|
|
||||||
|
nonExistingLangFile = "NON-EXISTING LANGUAGE" ---
|
||||||
|
|
||||||
|
|
||||||
|
allLangOptions st lang = unionOptions (optionsOfLang st lang) (globalOptions st)
|
||||||
|
|
||||||
|
-- construct state
|
||||||
|
|
||||||
|
stateGrammar st cf mo opts = StGr ((st,cf,mo),opts)
|
||||||
|
|
||||||
|
initShellState ab fs gs opts =
|
||||||
|
ShSt (Just ab, [(getLangName f, ((f,True),g)) | (f,g) <- zip fs gs], opts)
|
||||||
|
emptyInitShellState opts = ShSt (Nothing, [], opts)
|
||||||
|
|
||||||
|
-- the second-last part of a file name is the default language name
|
||||||
|
getLangName :: String -> Language
|
||||||
|
getLangName file = language (if notElem '.' file then file else langname) where
|
||||||
|
elif = reverse file
|
||||||
|
xiferp = tail (dropWhile (/='.') elif)
|
||||||
|
langname = reverse (takeWhile (flip notElem "./") xiferp)
|
||||||
|
|
||||||
|
-- option -language=foo overrides the default language name
|
||||||
|
getLangNameOpt :: Options -> String -> Language
|
||||||
|
getLangNameOpt opts file =
|
||||||
|
maybe (getLangName file) language $ getOptVal opts useLanguage
|
||||||
|
-}
|
||||||
|
-- modify state
|
||||||
|
|
||||||
|
type ShellStateOper = ShellState -> ShellState
|
||||||
|
|
||||||
|
reinitShellState :: ShellStateOper
|
||||||
|
reinitShellState = const emptyShellState
|
||||||
|
|
||||||
|
{-
|
||||||
|
languageOn = languageOnOff True
|
||||||
|
languageOff = languageOnOff False
|
||||||
|
|
||||||
|
languageOnOff :: Bool -> Language -> ShellStateOper
|
||||||
|
languageOnOff b lang (ShSt (ab,gs,os)) = ShSt (ab, gs', os) where
|
||||||
|
gs' = [if lang==l then (l,((f,b),g)) else i | i@(l,((f,_),g)) <- gs]
|
||||||
|
|
||||||
|
updateLanguage :: FilePath -> (Language, StateConcrete) -> ShellStateOper
|
||||||
|
updateLanguage file (lang,gr) (ShSt (ab,gs,os)) =
|
||||||
|
ShSt (ab, updateAssoc (lang,((file,True),gr)) gs, os') where
|
||||||
|
os' = changeOptVal os useLanguage (prLanguage lang) -- actualizes the new lang
|
||||||
|
|
||||||
|
initWithAbstract :: AbstractST -> ShellStateOper
|
||||||
|
initWithAbstract ab st@(ShSt (ma,cs,os)) =
|
||||||
|
maybe (ShSt (Just ab,cs,os)) (const st) ma
|
||||||
|
|
||||||
|
removeLanguage :: Language -> ShellStateOper
|
||||||
|
removeLanguage lang (ShSt (ab,gs,os)) = ShSt (ab,removeAssoc lang gs, os)
|
||||||
|
-}
|
||||||
|
changeOptions :: (Options -> Options) -> ShellStateOper
|
||||||
|
changeOptions f (ShSt a c cs can src cfs ms os ff ts ss) =
|
||||||
|
ShSt a c cs can src cfs ms (f os) ff ts ss
|
||||||
|
|
||||||
|
changeModTimes :: [(FilePath,ModTime)] -> ShellStateOper
|
||||||
|
changeModTimes mfs (ShSt a c cs can src cfs ms os ff ts ss) =
|
||||||
|
ShSt a c cs can src cfs ms os ff' ts ss
|
||||||
|
where
|
||||||
|
ff' = mfs ++ [mf | mf@(f,_) <- ff, notElem f (map fst mfs)]
|
||||||
|
|
||||||
|
addGlobalOptions :: Options -> ShellStateOper
|
||||||
|
addGlobalOptions = changeOptions . addOptions
|
||||||
|
|
||||||
|
removeGlobalOptions :: Options -> ShellStateOper
|
||||||
|
removeGlobalOptions = changeOptions . removeOptions
|
||||||
|
|
||||||
98
src/GF/Compile/Update.hs
Normal file
98
src/GF/Compile/Update.hs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
module Update where
|
||||||
|
|
||||||
|
import Ident
|
||||||
|
import Grammar
|
||||||
|
import PrGrammar
|
||||||
|
import Modules
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import List
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- update a resource module by adding a new or changing an old definition
|
||||||
|
|
||||||
|
updateRes :: SourceGrammar -> Ident -> Ident -> Info -> SourceGrammar
|
||||||
|
updateRes gr@(MGrammar ms) m i info = MGrammar $ map upd ms where
|
||||||
|
upd (n,mod)
|
||||||
|
| n /= m = (n,mod)
|
||||||
|
| n == m = case mod of
|
||||||
|
ModMod r -> (m,ModMod $ updateModule r i info)
|
||||||
|
_ -> (n,mod) --- no error msg
|
||||||
|
|
||||||
|
-- combine a list of definitions into a balanced binary search tree
|
||||||
|
|
||||||
|
buildAnyTree :: [(Ident,Info)] -> Err (BinTree (Ident, Info))
|
||||||
|
buildAnyTree ias = do
|
||||||
|
ias' <- combineAnyInfos ias
|
||||||
|
return $ buildTree ias'
|
||||||
|
|
||||||
|
|
||||||
|
-- unifying information for abstract, resource, and concrete
|
||||||
|
|
||||||
|
combineAnyInfos :: [(Ident,Info)] -> Err [(Ident,Info)]
|
||||||
|
combineAnyInfos = combineInfos unifyAnyInfo
|
||||||
|
|
||||||
|
unifyAnyInfo :: Ident -> Info -> Info -> Err Info
|
||||||
|
unifyAnyInfo c i j = errIn ("combining information for" +++ prt c) $ case (i,j) of
|
||||||
|
(AbsCat mc1 mf1, AbsCat mc2 mf2) ->
|
||||||
|
liftM2 AbsCat (unifPerhaps mc1 mc2) (unifPerhaps mf1 mf2) ---- adding constrs
|
||||||
|
(AbsFun mt1 md1, AbsFun mt2 md2) ->
|
||||||
|
liftM2 AbsFun (unifPerhaps mt1 mt2) (unifAbsDefs md1 md2) ---- adding defs
|
||||||
|
|
||||||
|
(ResParam mt1, ResParam mt2) -> liftM ResParam $ unifPerhaps mt1 mt2
|
||||||
|
(ResOper mt1 m1, ResOper mt2 m2) ->
|
||||||
|
liftM2 ResOper (unifPerhaps mt1 mt2) (unifPerhaps m1 m2)
|
||||||
|
|
||||||
|
(CncCat mc1 mf1 mp1, CncCat mc2 mf2 mp2) ->
|
||||||
|
liftM3 CncCat (unifPerhaps mc1 mc2) (unifPerhaps mf1 mf2) (unifPerhaps mp1 mp2)
|
||||||
|
(CncFun m mt1 md1, CncFun _ mt2 md2) ->
|
||||||
|
liftM2 (CncFun m) (unifPerhaps mt1 mt2) (unifPerhaps md1 md2) ---- adding defs
|
||||||
|
|
||||||
|
_ -> Bad $ "cannot unify information for" +++ show i
|
||||||
|
|
||||||
|
--- these auxiliaries should be somewhere else since they don't use the info types
|
||||||
|
|
||||||
|
groupInfos :: Eq a => [(a,b)] -> [[(a,b)]]
|
||||||
|
groupInfos = groupBy (\i j -> fst i == fst j)
|
||||||
|
|
||||||
|
sortInfos :: Ord a => [(a,b)] -> [(a,b)]
|
||||||
|
sortInfos = sortBy (\i j -> compare (fst i) (fst j))
|
||||||
|
|
||||||
|
combineInfos :: Ord a => (a -> b -> b -> Err b) -> [(a,b)] -> Err [(a,b)]
|
||||||
|
combineInfos f ris = do
|
||||||
|
let riss = groupInfos $ sortInfos ris
|
||||||
|
mapM (unifyInfos f) riss
|
||||||
|
|
||||||
|
unifyInfos :: (a -> b -> b -> Err b) -> [(a,b)] -> Err (a,b)
|
||||||
|
unifyInfos _ [] = Bad "empty info list"
|
||||||
|
unifyInfos unif ris = do
|
||||||
|
let c = fst $ head ris
|
||||||
|
let infos = map snd ris
|
||||||
|
let ([i],is) = splitAt 1 infos
|
||||||
|
info <- foldM (unif c) i is
|
||||||
|
return (c,info)
|
||||||
|
|
||||||
|
tryInsert :: Ord a => (b -> b -> Err b) -> (b -> b) ->
|
||||||
|
BinTree (a,b) -> (a,b) -> Err (BinTree (a,b))
|
||||||
|
tryInsert unif indir tree z@(x, info) = case tree of
|
||||||
|
NT -> return $ BT (x, indir info) NT NT
|
||||||
|
BT c@(a,info0) left right
|
||||||
|
| x < a -> do
|
||||||
|
left' <- tryInsert unif indir left z
|
||||||
|
return $ BT c left' right
|
||||||
|
| x > a -> do
|
||||||
|
right' <- tryInsert unif indir right z
|
||||||
|
return $ BT c left right'
|
||||||
|
| x == a -> do
|
||||||
|
info' <- unif info info0
|
||||||
|
return $ BT (x,info') left right
|
||||||
|
|
||||||
|
--- addToMaybeList m c = maybe (return c) (\old -> return (c ++ old)) m
|
||||||
|
|
||||||
|
unifAbsDefs :: Perh Term -> Perh Term -> Err (Perh Term)
|
||||||
|
unifAbsDefs p1 p2 = case (p1,p2) of
|
||||||
|
(Nope, _) -> return p2
|
||||||
|
(_, Nope) -> return p1
|
||||||
|
(Yes (Eqs bs), Yes (Eqs ds)) -> return $ yes $ Eqs $ bs ++ ds --- order!
|
||||||
|
_ -> Bad "update conflict"
|
||||||
7
src/GF/Data/ErrM.hs
Normal file
7
src/GF/Data/ErrM.hs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module ErrM (
|
||||||
|
module Operations
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
-- hack for BNFC generated files. AR 21/9/2003
|
||||||
559
src/GF/Data/Operations.hs
Normal file
559
src/GF/Data/Operations.hs
Normal file
@@ -0,0 +1,559 @@
|
|||||||
|
module Operations where
|
||||||
|
|
||||||
|
import Char (isSpace, toUpper, isSpace, isDigit)
|
||||||
|
import List (nub, sortBy, sort, deleteBy, nubBy)
|
||||||
|
import Monad (liftM2)
|
||||||
|
|
||||||
|
infixr 5 +++
|
||||||
|
infixr 5 ++-
|
||||||
|
infixr 5 ++++
|
||||||
|
infixr 5 +++++
|
||||||
|
infixl 9 !?
|
||||||
|
|
||||||
|
-- some auxiliary GF operations. AR 19/6/1998 -- 6/2/2001
|
||||||
|
-- Copyright (c) Aarne Ranta 1998-2000, under GNU General Public License (see GPL)
|
||||||
|
|
||||||
|
ifNull :: b -> ([a] -> b) -> [a] -> b
|
||||||
|
ifNull b f xs = if null xs then b else f xs
|
||||||
|
|
||||||
|
-- the Error monad
|
||||||
|
|
||||||
|
data Err a = Ok a | Bad String -- like Maybe type with error msgs
|
||||||
|
deriving (Read, Show, Eq)
|
||||||
|
|
||||||
|
instance Monad Err where
|
||||||
|
return = Ok
|
||||||
|
Ok a >>= f = f a
|
||||||
|
Bad s >>= f = Bad s
|
||||||
|
|
||||||
|
-- analogue of maybe
|
||||||
|
err :: (String -> b) -> (a -> b) -> Err a -> b
|
||||||
|
err d f e = case e of
|
||||||
|
Ok a -> f a
|
||||||
|
Bad s -> d s
|
||||||
|
|
||||||
|
-- add msg s to Maybe failures
|
||||||
|
maybeErr :: String -> Maybe a -> Err a
|
||||||
|
maybeErr s = maybe (Bad s) Ok
|
||||||
|
|
||||||
|
testErr :: Bool -> String -> Err ()
|
||||||
|
testErr cond msg = if cond then return () else Bad msg
|
||||||
|
|
||||||
|
errVal :: a -> Err a -> a
|
||||||
|
errVal a = err (const a) id
|
||||||
|
|
||||||
|
errIn :: String -> Err a -> Err a
|
||||||
|
errIn msg = err (\s -> Bad (s ++++ "OCCURRED IN" ++++ msg)) return
|
||||||
|
|
||||||
|
-- used for extra error reports when developing GF
|
||||||
|
derrIn :: String -> Err a -> Err a
|
||||||
|
derrIn m = errIn m -- id
|
||||||
|
|
||||||
|
performOps :: [a -> Err a] -> a -> Err a
|
||||||
|
performOps ops a = case ops of
|
||||||
|
f:fs -> f a >>= performOps fs
|
||||||
|
[] -> return a
|
||||||
|
|
||||||
|
repeatUntilErr :: (a -> Bool) -> (a -> Err a) -> a -> Err a
|
||||||
|
repeatUntilErr cond f a = if cond a then return a else f a >>= repeatUntilErr cond f
|
||||||
|
|
||||||
|
repeatUntil :: (a -> Bool) -> (a -> a) -> a -> a
|
||||||
|
repeatUntil cond f a = if cond a then a else repeatUntil cond f (f a)
|
||||||
|
|
||||||
|
okError :: Err a -> a
|
||||||
|
okError = err (error "no result Ok") id
|
||||||
|
|
||||||
|
isNotError :: Err a -> Bool
|
||||||
|
isNotError = err (const False) (const True)
|
||||||
|
|
||||||
|
showBad :: Show a => String -> a -> Err b
|
||||||
|
showBad s a = Bad (s +++ show a)
|
||||||
|
|
||||||
|
lookupErr :: (Eq a,Show a) => a -> [(a,b)] -> Err b
|
||||||
|
lookupErr a abs = maybeErr ("Unknown" +++ show a) (lookup a abs)
|
||||||
|
|
||||||
|
lookupErrMsg :: (Eq a,Show a) => String -> a -> [(a,b)] -> Err b
|
||||||
|
lookupErrMsg m a abs = maybeErr (m +++ "gave unknown" +++ show a) (lookup a abs)
|
||||||
|
|
||||||
|
lookupDefault :: Eq a => b -> a -> [(a,b)] -> b
|
||||||
|
lookupDefault d x l = maybe d id $ lookup x l
|
||||||
|
|
||||||
|
updateLookupList :: Eq a => (a,b) -> [(a,b)] -> [(a,b)]
|
||||||
|
updateLookupList ab abs = insert ab [] abs where
|
||||||
|
insert c cc [] = cc ++ [c]
|
||||||
|
insert (a,b) cc ((a',b'):cc') = if a == a'
|
||||||
|
then cc ++ [(a,b)] ++ cc'
|
||||||
|
else insert (a,b) (cc ++ [(a',b')]) cc'
|
||||||
|
|
||||||
|
mapPairListM :: Monad m => ((a,b) -> m c) -> [(a,b)] -> m [(a,c)]
|
||||||
|
mapPairListM f xys =
|
||||||
|
do yy' <- mapM f xys
|
||||||
|
return (zip (map fst xys) yy')
|
||||||
|
|
||||||
|
mapPairsM :: Monad m => (b -> m c) -> [(a,b)] -> m [(a,c)]
|
||||||
|
mapPairsM f xys =
|
||||||
|
do let (xx,yy) = unzip xys
|
||||||
|
yy' <- mapM f yy
|
||||||
|
return (zip xx yy')
|
||||||
|
|
||||||
|
pairM :: Monad a => (b -> a c) -> (b,b) -> a (c,c)
|
||||||
|
pairM op (t1,t2) = liftM2 (,) (op t1) (op t2)
|
||||||
|
|
||||||
|
-- like mapM, but continue instead of halting with Err
|
||||||
|
mapErr :: (a -> Err b) -> [a] -> Err ([b], String)
|
||||||
|
mapErr f xs = Ok (ys, unlines ss)
|
||||||
|
where
|
||||||
|
(ys,ss) = ([y | Ok y <- fxs], [s | Bad s <- fxs])
|
||||||
|
fxs = map f xs
|
||||||
|
|
||||||
|
-- !! with the error monad
|
||||||
|
(!?) :: [a] -> Int -> Err a
|
||||||
|
xs !? i = foldr (const . return) (Bad "too few elements in list") $ drop i xs
|
||||||
|
|
||||||
|
errList :: Err [a] -> [a]
|
||||||
|
errList = errVal []
|
||||||
|
|
||||||
|
singleton :: a -> [a]
|
||||||
|
singleton = (:[])
|
||||||
|
|
||||||
|
-- checking
|
||||||
|
|
||||||
|
checkUnique :: (Show a, Eq a) => [a] -> [String]
|
||||||
|
checkUnique ss = ["overloaded" +++ show s | s <- nub overloads] where
|
||||||
|
overloads = filter overloaded ss
|
||||||
|
overloaded s = length (filter (==s) ss) > 1
|
||||||
|
|
||||||
|
titleIfNeeded :: a -> [a] -> [a]
|
||||||
|
titleIfNeeded a [] = []
|
||||||
|
titleIfNeeded a as = a:as
|
||||||
|
|
||||||
|
errMsg :: Err a -> [String]
|
||||||
|
errMsg (Bad m) = [m]
|
||||||
|
errMsg _ = []
|
||||||
|
|
||||||
|
errAndMsg :: Err a -> Err (a,[String])
|
||||||
|
errAndMsg (Bad m) = Bad m
|
||||||
|
errAndMsg (Ok a) = return (a,[])
|
||||||
|
|
||||||
|
-- a three-valued maybe type to express indirections
|
||||||
|
|
||||||
|
data Perhaps a b = Yes a | May b | Nope deriving (Show,Read,Eq,Ord)
|
||||||
|
|
||||||
|
yes = Yes
|
||||||
|
may = May
|
||||||
|
nope = Nope
|
||||||
|
|
||||||
|
mapP :: (a -> c) -> Perhaps a b -> Perhaps c b
|
||||||
|
mapP f p = case p of
|
||||||
|
Yes a -> Yes (f a)
|
||||||
|
May b -> May b
|
||||||
|
Nope -> Nope
|
||||||
|
|
||||||
|
-- this is what happens when matching two values in the same module
|
||||||
|
unifPerhaps :: Perhaps a b -> Perhaps a b -> Err (Perhaps a b)
|
||||||
|
unifPerhaps p1 p2 = case (p1,p2) of
|
||||||
|
(Nope, _) -> return p2
|
||||||
|
(_, Nope) -> return p1
|
||||||
|
_ -> Bad "update conflict"
|
||||||
|
|
||||||
|
-- this is what happens when updating a module extension
|
||||||
|
updatePerhaps :: b -> Perhaps a b -> Perhaps a b -> Err (Perhaps a b)
|
||||||
|
updatePerhaps old p1 p2 = case (p1,p2) of
|
||||||
|
(Yes a, Nope) -> return $ may old
|
||||||
|
(May older,Nope) -> return $ may older
|
||||||
|
(_, May a) -> Bad "strange indirection"
|
||||||
|
_ -> unifPerhaps p1 p2
|
||||||
|
|
||||||
|
-- binary search trees
|
||||||
|
|
||||||
|
data BinTree a = NT | BT a (BinTree a) (BinTree a) deriving (Show,Read)
|
||||||
|
|
||||||
|
isInBinTree :: (Ord a) => a -> BinTree a -> Bool
|
||||||
|
isInBinTree x tree = case tree of
|
||||||
|
NT -> False
|
||||||
|
BT a left right
|
||||||
|
| x < a -> isInBinTree x left
|
||||||
|
| x > a -> isInBinTree x right
|
||||||
|
| x == a -> True
|
||||||
|
|
||||||
|
-- quick method to see if two trees have common elements
|
||||||
|
-- the complexity is O(log |old|, |new|) so the heuristic is that new is smaller
|
||||||
|
|
||||||
|
commonsInTree :: (Ord a) => BinTree (a,b) -> BinTree (a,b) -> [(a,(b,b))]
|
||||||
|
commonsInTree old new = foldr inOld [] new' where
|
||||||
|
new' = tree2list new
|
||||||
|
inOld (x,v) xs = case justLookupTree x old of
|
||||||
|
Ok v' -> (x,(v',v)) : xs
|
||||||
|
_ -> xs
|
||||||
|
|
||||||
|
justLookupTree :: (Ord a) => a -> BinTree (a,b) -> Err b
|
||||||
|
justLookupTree = lookupTree (const [])
|
||||||
|
|
||||||
|
lookupTree :: (Ord a) => (a -> String) -> a -> BinTree (a,b) -> Err b
|
||||||
|
lookupTree pr x tree = case tree of
|
||||||
|
NT -> Bad ("no occurrence of element" +++ pr x)
|
||||||
|
BT (a,b) left right
|
||||||
|
| x < a -> lookupTree pr x left
|
||||||
|
| x > a -> lookupTree pr x right
|
||||||
|
| x == a -> return b
|
||||||
|
|
||||||
|
lookupTreeEq :: (Ord a) =>
|
||||||
|
(a -> String) -> (a -> a -> Bool) -> a -> BinTree (a,b) -> Err b
|
||||||
|
lookupTreeEq pr eq x tree = case tree of
|
||||||
|
NT -> Bad ("no occurrence of element equal to" +++ pr x)
|
||||||
|
BT (a,b) left right
|
||||||
|
| eq x a -> return b -- a weaker equality relation than ==
|
||||||
|
| x < a -> lookupTreeEq pr eq x left
|
||||||
|
| x > a -> lookupTreeEq pr eq x right
|
||||||
|
|
||||||
|
lookupTreeMany :: Ord a => (a -> String) -> [BinTree (a,b)] -> a -> Err b
|
||||||
|
lookupTreeMany pr (t:ts) x = case lookupTree pr x t of
|
||||||
|
Ok v -> return v
|
||||||
|
_ -> lookupTreeMany pr ts x
|
||||||
|
lookupTreeMany pr [] x = Bad $ "failed to find" +++ pr x
|
||||||
|
|
||||||
|
-- destructive update
|
||||||
|
|
||||||
|
updateTree :: (Ord a) => (a,b) -> BinTree (a,b) -> BinTree (a,b)
|
||||||
|
updateTree = updateTreeGen True
|
||||||
|
|
||||||
|
-- destructive or not
|
||||||
|
|
||||||
|
updateTreeGen :: (Ord a) => Bool -> (a,b) -> BinTree (a,b) -> BinTree (a,b)
|
||||||
|
updateTreeGen destr z@(x,y) tree = case tree of
|
||||||
|
NT -> BT z NT NT
|
||||||
|
BT c@(a,b) left right
|
||||||
|
| x < a -> let left' = updateTree z left in BT c left' right
|
||||||
|
| x > a -> let right' = updateTree z right in BT c left right'
|
||||||
|
| otherwise -> if destr
|
||||||
|
then BT z left right -- removing the old value of a
|
||||||
|
else tree -- retaining the old value if one exists
|
||||||
|
|
||||||
|
updateTreeEq ::
|
||||||
|
(Ord a) => (a -> a -> Bool) -> (a,b) -> BinTree (a,b) -> BinTree (a,b)
|
||||||
|
updateTreeEq eq z@(x,y) tree = case tree of
|
||||||
|
NT -> BT z NT NT
|
||||||
|
BT c@(a,b) left right
|
||||||
|
| eq x a -> BT (a,y) left right -- removing the old value of a
|
||||||
|
| x < a -> let left' = updateTree z left in BT c left' right
|
||||||
|
| x > a -> let right' = updateTree z right in BT c left right'
|
||||||
|
|
||||||
|
updatesTree :: (Ord a) => [(a,b)] -> BinTree (a,b) -> BinTree (a,b)
|
||||||
|
updatesTree (z:zs) tr = updateTree z t where t = updatesTree zs tr
|
||||||
|
updatesTree [] tr = tr
|
||||||
|
|
||||||
|
updatesTreeNondestr :: (Ord a) => [(a,b)] -> BinTree (a,b) -> BinTree (a,b)
|
||||||
|
updatesTreeNondestr xs tr = case xs of
|
||||||
|
(z:zs) -> updateTreeGen False z t where t = updatesTreeNondestr zs tr
|
||||||
|
_ -> tr
|
||||||
|
|
||||||
|
buildTree :: (Ord a) => [(a,b)] -> BinTree (a,b)
|
||||||
|
buildTree = sorted2tree . sortBy fs where
|
||||||
|
fs (x,_) (y,_)
|
||||||
|
| x < y = LT
|
||||||
|
| x > y = GT
|
||||||
|
| True = EQ
|
||||||
|
-- buildTree zz = updatesTree zz NT
|
||||||
|
|
||||||
|
sorted2tree :: [(a,b)] -> BinTree (a,b)
|
||||||
|
sorted2tree [] = NT
|
||||||
|
sorted2tree xs = BT x (sorted2tree t1) (sorted2tree t2) where
|
||||||
|
(t1,(x:t2)) = splitAt (length xs `div` 2) xs
|
||||||
|
|
||||||
|
mapTree :: (a -> b) -> BinTree a -> BinTree b
|
||||||
|
mapTree f NT = NT
|
||||||
|
mapTree f (BT a left right) = BT (f a) (mapTree f left) (mapTree f right)
|
||||||
|
|
||||||
|
mapMTree :: Monad m => (a -> m b) -> BinTree a -> m (BinTree b)
|
||||||
|
mapMTree f NT = return NT
|
||||||
|
mapMTree f (BT a left right) = do
|
||||||
|
a' <- f a
|
||||||
|
left' <- mapMTree f left
|
||||||
|
right' <- mapMTree f right
|
||||||
|
return $ BT a' left' right'
|
||||||
|
|
||||||
|
tree2list :: BinTree a -> [a] -- inorder
|
||||||
|
tree2list NT = []
|
||||||
|
tree2list (BT z left right) = tree2list left ++ [z] ++ tree2list right
|
||||||
|
|
||||||
|
depthTree :: BinTree a -> Int
|
||||||
|
depthTree NT = 0
|
||||||
|
depthTree (BT _ left right) = 1 + max (depthTree left) (depthTree right)
|
||||||
|
|
||||||
|
mergeTrees :: Ord a => BinTree (a,b) -> BinTree (a,b) -> BinTree (a,[b])
|
||||||
|
mergeTrees old new = foldr upd new' (tree2list old) where
|
||||||
|
upd xy@(x,y) tree = case tree of
|
||||||
|
NT -> BT (x,[y]) NT NT
|
||||||
|
BT (a,bs) left right
|
||||||
|
| x < a -> let left' = upd xy left in BT (a,bs) left' right
|
||||||
|
| x > a -> let right' = upd xy right in BT (a,bs) left right'
|
||||||
|
| otherwise -> BT (a, y:bs) left right -- adding the new value
|
||||||
|
new' = mapTree (\ (i,d) -> (i,[d])) new
|
||||||
|
|
||||||
|
|
||||||
|
-- parsing
|
||||||
|
|
||||||
|
type WParser a b = [a] -> [(b,[a])] -- old Wadler style parser
|
||||||
|
|
||||||
|
wParseResults :: WParser a b -> [a] -> [b]
|
||||||
|
wParseResults p aa = [b | (b,[]) <- p aa]
|
||||||
|
|
||||||
|
-- printing
|
||||||
|
|
||||||
|
indent :: Int -> String -> String
|
||||||
|
indent i s = replicate i ' ' ++ s
|
||||||
|
|
||||||
|
a +++ b = a ++ " " ++ b
|
||||||
|
a ++- "" = a
|
||||||
|
a ++- b = a +++ b
|
||||||
|
a ++++ b = a ++ "\n" ++ b
|
||||||
|
a +++++ b = a ++ "\n\n" ++ b
|
||||||
|
|
||||||
|
prUpper :: String -> String
|
||||||
|
prUpper s = s1 ++ s2' where
|
||||||
|
(s1,s2) = span isSpace s
|
||||||
|
s2' = case s2 of
|
||||||
|
c:t -> toUpper c : t
|
||||||
|
_ -> s2
|
||||||
|
|
||||||
|
prReplicate n s = concat (replicate n s)
|
||||||
|
|
||||||
|
prTList t ss = case ss of
|
||||||
|
[] -> ""
|
||||||
|
[s] -> s
|
||||||
|
s:ss -> s ++ t ++ prTList t ss
|
||||||
|
|
||||||
|
prQuotedString x = "\"" ++ restoreEscapes x ++ "\""
|
||||||
|
|
||||||
|
prParenth s = if s == "" then "" else "(" ++ s ++ ")"
|
||||||
|
|
||||||
|
prCurly s = "{" ++ s ++ "}"
|
||||||
|
prBracket s = "[" ++ s ++ "]"
|
||||||
|
|
||||||
|
prArgList xx = prParenth (prTList "," xx)
|
||||||
|
|
||||||
|
prSemicList = prTList " ; "
|
||||||
|
|
||||||
|
prCurlyList = prCurly . prSemicList
|
||||||
|
|
||||||
|
restoreEscapes s =
|
||||||
|
case s of
|
||||||
|
[] -> []
|
||||||
|
'"' : t -> '\\' : '"' : restoreEscapes t
|
||||||
|
'\\': t -> '\\' : '\\' : restoreEscapes t
|
||||||
|
c : t -> c : restoreEscapes t
|
||||||
|
|
||||||
|
numberedParagraphs :: [[String]] -> [String]
|
||||||
|
numberedParagraphs t = case t of
|
||||||
|
[] -> []
|
||||||
|
p:[] -> p
|
||||||
|
_ -> concat [(show n ++ ".") : s | (n,s) <- zip [1..] t]
|
||||||
|
|
||||||
|
prConjList :: String -> [String] -> String
|
||||||
|
prConjList c [] = ""
|
||||||
|
prConjList c [s] = s
|
||||||
|
prConjList c [s,t] = s +++ c +++ t
|
||||||
|
prConjList c (s:tt) = s ++ "," +++ prConjList c tt
|
||||||
|
|
||||||
|
prIfEmpty :: String -> String -> String -> String -> String
|
||||||
|
prIfEmpty em _ _ [] = em
|
||||||
|
prIfEmpty em nem1 nem2 s = nem1 ++ s ++ nem2
|
||||||
|
|
||||||
|
-- Thomas Hallgren's wrap lines
|
||||||
|
--- optWrapLines = if argFlag "wraplines" True then wrapLines 0 else id
|
||||||
|
wrapLines n "" = ""
|
||||||
|
wrapLines n s@(c:cs) =
|
||||||
|
if isSpace c
|
||||||
|
then c:wrapLines (n+1) cs
|
||||||
|
else case lex s of
|
||||||
|
[(w,rest)] -> if n'>=76
|
||||||
|
then '\n':w++wrapLines l rest
|
||||||
|
else w++wrapLines n' rest
|
||||||
|
where n' = n+l
|
||||||
|
l = length w
|
||||||
|
_ -> s -- give up!!
|
||||||
|
|
||||||
|
-- LaTeX code producing functions
|
||||||
|
|
||||||
|
dollar s = '$' : s ++ "$"
|
||||||
|
mbox s = "\\mbox{" ++ s ++ "}"
|
||||||
|
ital s = "{\\em" +++ s ++ "}"
|
||||||
|
boldf s = "{\\bf" +++ s ++ "}"
|
||||||
|
verbat s = "\\verbat!" ++ s ++ "!"
|
||||||
|
|
||||||
|
mkLatexFile s = begindocument +++++ s +++++ enddocument
|
||||||
|
|
||||||
|
begindocument =
|
||||||
|
"\\documentclass[a4paper,11pt]{article}" ++++ -- M.F. 25/01-02
|
||||||
|
"\\setlength{\\parskip}{2mm}" ++++
|
||||||
|
"\\setlength{\\parindent}{0mm}" ++++
|
||||||
|
"\\setlength{\\oddsidemargin}{0mm}" ++++
|
||||||
|
"\\setlength{\\evensidemargin}{-2mm}" ++++
|
||||||
|
"\\setlength{\\topmargin}{-8mm}" ++++
|
||||||
|
"\\setlength{\\textheight}{240mm}" ++++
|
||||||
|
"\\setlength{\\textwidth}{158mm}" ++++
|
||||||
|
"\\begin{document}\n"
|
||||||
|
|
||||||
|
enddocument =
|
||||||
|
"\n\\end{document}\n"
|
||||||
|
|
||||||
|
sortByLongest :: [[a]] -> [[a]]
|
||||||
|
sortByLongest = sortBy longer where
|
||||||
|
longer x y
|
||||||
|
| x' > y' = LT
|
||||||
|
| x' < y' = GT
|
||||||
|
| True = EQ
|
||||||
|
where
|
||||||
|
x' = length x
|
||||||
|
y' = length y
|
||||||
|
|
||||||
|
combinations :: [[a]] -> [[a]]
|
||||||
|
combinations t = case t of
|
||||||
|
[] -> [[]]
|
||||||
|
aa:uu -> [a:u | a <- aa, u <- combinations uu]
|
||||||
|
|
||||||
|
mkTextFile :: String -> IO ()
|
||||||
|
mkTextFile name = do
|
||||||
|
s <- readFile name
|
||||||
|
let s' = prelude name ++ "\n\n" ++ heading name ++ "\n" ++ object s
|
||||||
|
writeFile (name ++ ".hs") s'
|
||||||
|
where
|
||||||
|
prelude name = "module " ++ name ++ " where"
|
||||||
|
heading name = "txt" ++ name ++ " ="
|
||||||
|
object s = mk s ++ " \"\""
|
||||||
|
mk s = unlines [" \"" ++ escs line ++ "\" ++ \"\\n\" ++" | line <- lines s]
|
||||||
|
escs s = case s of
|
||||||
|
c:cs | elem c "\"\\" -> '\\' : c : escs cs
|
||||||
|
c:cs -> c : escs cs
|
||||||
|
_ -> s
|
||||||
|
|
||||||
|
initFilePath :: FilePath -> FilePath
|
||||||
|
initFilePath f = reverse (dropWhile (/='/') (reverse f))
|
||||||
|
|
||||||
|
-- topological sorting with test of cyclicity
|
||||||
|
|
||||||
|
topoTest :: Eq a => [(a,[a])] -> Either [a] [[a]]
|
||||||
|
topoTest g = if length g' == length g then Left g' else Right (cyclesIn g ++[[]])
|
||||||
|
where
|
||||||
|
g' = topoSort g
|
||||||
|
|
||||||
|
cyclesIn :: Eq a => [(a,[a])] -> [[a]]
|
||||||
|
cyclesIn deps = nubb $ clean $ filt $ iterFix findDep immediate where
|
||||||
|
immediate = [[y,x] | (x,xs) <- deps, y <- xs]
|
||||||
|
findDep chains = [y:x:chain |
|
||||||
|
x:chain <- chains, (x',xs) <- deps, x' == x, y <- xs,
|
||||||
|
notElem y (init chain)]
|
||||||
|
|
||||||
|
clean = map remdup
|
||||||
|
nubb = nubBy (\x y -> y == reverse x)
|
||||||
|
filt = filter (\xs -> last xs == head xs)
|
||||||
|
remdup (x:xs) = x : remdup xs' where xs' = dropWhile (==x) xs
|
||||||
|
remdup [] = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
topoSort :: Eq a => [(a,[a])] -> [a]
|
||||||
|
topoSort g = reverse $ tsort 0 [ffs | ffs@(f,_) <- g, inDeg f == 0] [] where
|
||||||
|
tsort _ [] r = r
|
||||||
|
tsort k (ffs@(f,fs) : cs) r
|
||||||
|
| elem f r = tsort k cs r
|
||||||
|
| k > lx = r
|
||||||
|
| otherwise = tsort (k+1) cs (f : tsort (k+1) (info fs) r)
|
||||||
|
info hs = [(f,fs) | (f,fs) <- g, elem f hs]
|
||||||
|
inDeg f = length [t | (h,hs) <- g, t <- hs, t == f]
|
||||||
|
lx = length g
|
||||||
|
|
||||||
|
-- the generic fix point iterator
|
||||||
|
|
||||||
|
iterFix :: Eq a => ([a] -> [a]) -> [a] -> [a]
|
||||||
|
iterFix more start = iter start start
|
||||||
|
where
|
||||||
|
iter old new = if (null new')
|
||||||
|
then old
|
||||||
|
else iter (new' ++ old) new'
|
||||||
|
where
|
||||||
|
new' = filter (`notElem` old) (more new)
|
||||||
|
|
||||||
|
-- association lists
|
||||||
|
|
||||||
|
updateAssoc :: Eq a => (a,b) -> [(a,b)] -> [(a,b)]
|
||||||
|
updateAssoc ab@(a,b) as = case as of
|
||||||
|
(x,y): xs | x == a -> (a,b):xs
|
||||||
|
xy : xs -> xy : updateAssoc ab xs
|
||||||
|
[] -> [ab]
|
||||||
|
|
||||||
|
removeAssoc :: Eq a => a -> [(a,b)] -> [(a,b)]
|
||||||
|
removeAssoc a = filter ((/=a) . fst)
|
||||||
|
|
||||||
|
-- chop into separator-separated parts
|
||||||
|
|
||||||
|
chunks :: String -> [String] -> [[String]]
|
||||||
|
chunks sep ws = case span (/= sep) ws of
|
||||||
|
(a,_:b) -> a : bs where bs = chunks sep b
|
||||||
|
(a, []) -> if null a then [] else [a]
|
||||||
|
|
||||||
|
readIntArg :: String -> Int
|
||||||
|
readIntArg n = if (not (null n) && all isDigit n) then read n else 0
|
||||||
|
|
||||||
|
|
||||||
|
-- state monad with error; from Agda 6/11/2001
|
||||||
|
|
||||||
|
newtype STM s a = STM (s -> Err (a,s))
|
||||||
|
|
||||||
|
appSTM :: STM s a -> s -> Err (a,s)
|
||||||
|
appSTM (STM f) s = f s
|
||||||
|
|
||||||
|
stm :: (s -> Err (a,s)) -> STM s a
|
||||||
|
stm = STM
|
||||||
|
|
||||||
|
stmr :: (s -> (a,s)) -> STM s a
|
||||||
|
stmr f = stm (\s -> return (f s))
|
||||||
|
|
||||||
|
instance Monad (STM s) where
|
||||||
|
return a = STM (\s -> return (a,s))
|
||||||
|
STM c >>= f = STM (\s -> do
|
||||||
|
(x,s') <- c s
|
||||||
|
let STM f' = f x
|
||||||
|
f' s')
|
||||||
|
|
||||||
|
readSTM :: STM s s
|
||||||
|
readSTM = stmr (\s -> (s,s))
|
||||||
|
|
||||||
|
updateSTM :: (s -> s) -> STM s ()
|
||||||
|
updateSTM f = stmr (\s -> ((),f s))
|
||||||
|
|
||||||
|
writeSTM :: s -> STM s ()
|
||||||
|
writeSTM s = stmr (const ((),s))
|
||||||
|
|
||||||
|
done :: Monad m => m ()
|
||||||
|
done = return ()
|
||||||
|
|
||||||
|
class Monad m => ErrorMonad m where
|
||||||
|
raise :: String -> m a
|
||||||
|
handle :: m a -> (String -> m a) -> m a
|
||||||
|
handle_ :: m a -> m a -> m a
|
||||||
|
handle_ a b = a `handle` (\_ -> b)
|
||||||
|
|
||||||
|
instance ErrorMonad Err where
|
||||||
|
raise = Bad
|
||||||
|
handle a@(Ok _) _ = a
|
||||||
|
handle (Bad i) f = f i
|
||||||
|
|
||||||
|
instance ErrorMonad (STM s) where
|
||||||
|
raise msg = STM (\s -> raise msg)
|
||||||
|
handle (STM f) g = STM (\s -> (f s)
|
||||||
|
`handle` (\e -> let STM g' = (g e) in
|
||||||
|
g' s))
|
||||||
|
-- if the first check fails try another one
|
||||||
|
checkAgain :: ErrorMonad m => m a -> m a -> m a
|
||||||
|
checkAgain c1 c2 = handle_ c1 c2
|
||||||
|
|
||||||
|
checks :: ErrorMonad m => [m a] -> m a
|
||||||
|
checks [] = raise "no chance to pass"
|
||||||
|
checks cs = foldr1 checkAgain cs
|
||||||
|
|
||||||
|
allChecks :: ErrorMonad m => [m a] -> m [a]
|
||||||
|
allChecks ms = case ms of
|
||||||
|
(m: ms) -> let rs = allChecks ms in handle_ (liftM2 (:) m rs) rs
|
||||||
|
_ -> return []
|
||||||
|
|
||||||
118
src/GF/Data/OrdMap2.hs
Normal file
118
src/GF/Data/OrdMap2.hs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- The class of ordered finite maps
|
||||||
|
-- as described in section 2.2.2
|
||||||
|
|
||||||
|
-- and an example implementation,
|
||||||
|
-- derived from the implementation in appendix A.2
|
||||||
|
|
||||||
|
|
||||||
|
module OrdMap2 (OrdMap(..), Map) where
|
||||||
|
|
||||||
|
import List (intersperse)
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- the class of ordered finite maps
|
||||||
|
|
||||||
|
class OrdMap m where
|
||||||
|
emptyMap :: Ord s => m s a
|
||||||
|
(|->) :: Ord s => s -> a -> m s a
|
||||||
|
isEmptyMap :: Ord s => m s a -> Bool
|
||||||
|
(?) :: Ord s => m s a -> s -> Maybe a
|
||||||
|
lookupWith :: Ord s => a -> m s a -> s -> a
|
||||||
|
mergeWith :: Ord s => (a -> a -> a) -> m s a -> m s a -> m s a
|
||||||
|
unionMapWith :: Ord s => (a -> a -> a) -> [m s a] -> m s a
|
||||||
|
makeMapWith :: Ord s => (a -> a -> a) -> [(s,a)] -> m s a
|
||||||
|
assocs :: Ord s => m s a -> [(s,a)]
|
||||||
|
ordMap :: Ord s => [(s,a)] -> m s a
|
||||||
|
mapMap :: Ord s => (a -> b) -> m s a -> m s b
|
||||||
|
|
||||||
|
lookupWith z m s = case m ? s of
|
||||||
|
Just a -> a
|
||||||
|
Nothing -> z
|
||||||
|
|
||||||
|
unionMapWith join = union
|
||||||
|
where union [] = emptyMap
|
||||||
|
union [xs] = xs
|
||||||
|
union xyss = mergeWith join (union xss) (union yss)
|
||||||
|
where (xss, yss) = split xyss
|
||||||
|
split (x:y:xyss) = let (xs, ys) = split xyss in (x:xs, y:ys)
|
||||||
|
split xs = (xs, [])
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- finite maps as ordered associaiton lists,
|
||||||
|
-- paired with binary search trees
|
||||||
|
|
||||||
|
data Map s a = Map [(s,a)] (TreeMap s a)
|
||||||
|
|
||||||
|
instance (Eq s, Eq a) => Eq (Map s a) where
|
||||||
|
Map xs _ == Map ys _ = xs == ys
|
||||||
|
|
||||||
|
instance (Show s, Show a) => Show (Map s a) where
|
||||||
|
show (Map ass _) = "{" ++ concat (intersperse "," (map show' ass)) ++ "}"
|
||||||
|
where show' (s,a) = show s ++ "|->" ++ show a
|
||||||
|
|
||||||
|
instance OrdMap Map where
|
||||||
|
emptyMap = Map [] (makeTree [])
|
||||||
|
s |-> a = Map [(s,a)] (makeTree [(s,a)])
|
||||||
|
|
||||||
|
isEmptyMap (Map ass _) = null ass
|
||||||
|
|
||||||
|
Map _ tree ? s = lookupTree s tree
|
||||||
|
|
||||||
|
mergeWith join (Map xss _) (Map yss _) = Map xyss (makeTree xyss)
|
||||||
|
where xyss = merge xss yss
|
||||||
|
merge [] yss = yss
|
||||||
|
merge xss [] = xss
|
||||||
|
merge xss@(x@(s,x'):xss') yss@(y@(t,y'):yss')
|
||||||
|
= case compare s t of
|
||||||
|
LT -> x : merge xss' yss
|
||||||
|
GT -> y : merge xss yss'
|
||||||
|
EQ -> (s, join x' y') : merge xss' yss'
|
||||||
|
|
||||||
|
makeMapWith join [] = emptyMap
|
||||||
|
makeMapWith join [(s,a)] = s |-> a
|
||||||
|
makeMapWith join xyss = mergeWith join (makeMapWith join xss) (makeMapWith join yss)
|
||||||
|
where (xss, yss) = split xyss
|
||||||
|
split (x:y:xys) = let (xs, ys) = split xys in (x:xs, y:ys)
|
||||||
|
split xs = (xs, [])
|
||||||
|
|
||||||
|
assocs (Map xss _) = xss
|
||||||
|
ordMap xss = Map xss (makeTree xss)
|
||||||
|
|
||||||
|
mapMap f (Map ass atree) = Map [ (s,f a) | (s,a) <- ass ] (mapTree f atree)
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- binary search trees
|
||||||
|
-- for logarithmic lookup time
|
||||||
|
|
||||||
|
data TreeMap s a = Nil | Node (TreeMap s a) s a (TreeMap s a)
|
||||||
|
|
||||||
|
makeTree ass = tree
|
||||||
|
where
|
||||||
|
(tree,[]) = sl2bst (length ass) ass
|
||||||
|
sl2bst 0 ass = (Nil, ass)
|
||||||
|
sl2bst 1 ((s,a):ass) = (Node Nil s a Nil, ass)
|
||||||
|
sl2bst n ass = (Node ltree s a rtree, css)
|
||||||
|
where llen = (n-1) `div` 2
|
||||||
|
rlen = n - 1 - llen
|
||||||
|
(ltree, (s,a):bss) = sl2bst llen ass
|
||||||
|
(rtree, css) = sl2bst rlen bss
|
||||||
|
|
||||||
|
lookupTree s Nil = Nothing
|
||||||
|
lookupTree s (Node left s' a right)
|
||||||
|
= case compare s s' of
|
||||||
|
LT -> lookupTree s left
|
||||||
|
GT -> lookupTree s right
|
||||||
|
EQ -> Just a
|
||||||
|
|
||||||
|
mapTree f Nil = Nil
|
||||||
|
mapTree f (Node left s a right) = Node (mapTree f left) s (f a) (mapTree f right)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
111
src/GF/Data/OrdSet.hs
Normal file
111
src/GF/Data/OrdSet.hs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- The class of ordered sets
|
||||||
|
-- as described in section 2.2.1
|
||||||
|
|
||||||
|
-- and an example implementation,
|
||||||
|
-- derived from the implementation in appendix A.1
|
||||||
|
|
||||||
|
|
||||||
|
module OrdSet (OrdSet(..), Set) where
|
||||||
|
|
||||||
|
import List (intersperse)
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- the class of ordered sets
|
||||||
|
|
||||||
|
class OrdSet m where
|
||||||
|
emptySet :: Ord a => m a
|
||||||
|
unitSet :: Ord a => a -> m a
|
||||||
|
isEmpty :: Ord a => m a -> Bool
|
||||||
|
elemSet :: Ord a => a -> m a -> Bool
|
||||||
|
(<++>) :: Ord a => m a -> m a -> m a
|
||||||
|
(<\\>) :: Ord a => m a -> m a -> m a
|
||||||
|
plusMinus :: Ord a => m a -> m a -> (m a, m a)
|
||||||
|
union :: Ord a => [m a] -> m a
|
||||||
|
makeSet :: Ord a => [a] -> m a
|
||||||
|
elems :: Ord a => m a -> [a]
|
||||||
|
ordSet :: Ord a => [a] -> m a
|
||||||
|
limit :: Ord a => (a -> m a) -> m a -> m a
|
||||||
|
|
||||||
|
xs <++> ys = fst (plusMinus xs ys)
|
||||||
|
xs <\\> ys = snd (plusMinus xs ys)
|
||||||
|
plusMinus xs ys = (xs <++> ys, xs <\\> ys)
|
||||||
|
|
||||||
|
union [] = emptySet
|
||||||
|
union [xs] = xs
|
||||||
|
union xyss = union xss <++> union yss
|
||||||
|
where (xss, yss) = split xyss
|
||||||
|
split (x:y:xyss) = let (xs, ys) = split xyss in (x:xs, y:ys)
|
||||||
|
split xs = (xs, [])
|
||||||
|
|
||||||
|
makeSet xs = union (map unitSet xs)
|
||||||
|
|
||||||
|
limit more start = limit' (start, start)
|
||||||
|
where limit' (old, new)
|
||||||
|
| isEmpty new' = old
|
||||||
|
| otherwise = limit' (plusMinus new' old)
|
||||||
|
where new' = union (map more (elems new))
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- sets as ordered lists,
|
||||||
|
-- paired with a binary tree
|
||||||
|
|
||||||
|
data Set a = Set [a] (TreeSet a)
|
||||||
|
|
||||||
|
instance Eq a => Eq (Set a) where
|
||||||
|
Set xs _ == Set ys _ = xs == ys
|
||||||
|
|
||||||
|
instance Ord a => Ord (Set a) where
|
||||||
|
compare (Set xs _) (Set ys _) = compare xs ys
|
||||||
|
|
||||||
|
instance Show a => Show (Set a) where
|
||||||
|
show (Set xs _) = "{" ++ concat (intersperse "," (map show xs)) ++ "}"
|
||||||
|
|
||||||
|
instance OrdSet Set where
|
||||||
|
emptySet = Set [] (makeTree [])
|
||||||
|
unitSet a = Set [a] (makeTree [a])
|
||||||
|
|
||||||
|
isEmpty (Set xs _) = null xs
|
||||||
|
elemSet a (Set _ xt) = elemTree a xt
|
||||||
|
|
||||||
|
plusMinus (Set xs _) (Set ys _) = (Set ps (makeTree ps), Set ms (makeTree ms))
|
||||||
|
where (ps, ms) = plm xs ys
|
||||||
|
plm [] ys = (ys, [])
|
||||||
|
plm xs [] = (xs, xs)
|
||||||
|
plm xs@(x:xs') ys@(y:ys') = case compare x y of
|
||||||
|
LT -> let (ps, ms) = plm xs' ys in (x:ps, x:ms)
|
||||||
|
GT -> let (ps, ms) = plm xs ys' in (y:ps, ms)
|
||||||
|
EQ -> let (ps, ms) = plm xs' ys' in (x:ps, ms)
|
||||||
|
|
||||||
|
elems (Set xs _) = xs
|
||||||
|
ordSet xs = Set xs (makeTree xs)
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------
|
||||||
|
-- binary search trees
|
||||||
|
-- for logarithmic lookup time
|
||||||
|
|
||||||
|
data TreeSet a = Nil | Node (TreeSet a) a (TreeSet a)
|
||||||
|
|
||||||
|
makeTree xs = tree
|
||||||
|
where (tree,[]) = sl2bst (length xs) xs
|
||||||
|
sl2bst 0 xs = (Nil, xs)
|
||||||
|
sl2bst 1 (a:xs) = (Node Nil a Nil, xs)
|
||||||
|
sl2bst n xs = (Node ltree a rtree, zs)
|
||||||
|
where llen = (n-1) `div` 2
|
||||||
|
rlen = n - 1 - llen
|
||||||
|
(ltree, a:ys) = sl2bst llen xs
|
||||||
|
(rtree, zs) = sl2bst rlen ys
|
||||||
|
|
||||||
|
elemTree a Nil = False
|
||||||
|
elemTree a (Node ltree x rtree)
|
||||||
|
= case compare a x of
|
||||||
|
LT -> elemTree a ltree
|
||||||
|
GT -> elemTree a rtree
|
||||||
|
EQ -> True
|
||||||
|
|
||||||
|
|
||||||
143
src/GF/Data/Parsers.hs
Normal file
143
src/GF/Data/Parsers.hs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
module Parsers where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Char
|
||||||
|
|
||||||
|
|
||||||
|
infixr 2 |||, +||
|
||||||
|
infixr 3 ***
|
||||||
|
infixr 5 .>.
|
||||||
|
infixr 5 ...
|
||||||
|
infixr 5 ....
|
||||||
|
infixr 5 +..
|
||||||
|
infixr 5 ..+
|
||||||
|
infixr 6 |>
|
||||||
|
infixr 3 <<<
|
||||||
|
|
||||||
|
-- some parser combinators a` la Wadler and Hutton
|
||||||
|
-- no longer used in many places in GF
|
||||||
|
|
||||||
|
type Parser a b = [a] -> [(b,[a])]
|
||||||
|
|
||||||
|
parseResults :: Parser a b -> [a] -> [b]
|
||||||
|
parseResults p s = [x | (x,r) <- p s, null r]
|
||||||
|
|
||||||
|
parseResultErr :: Parser a b -> [a] -> Err b
|
||||||
|
parseResultErr p s = case parseResults p s of
|
||||||
|
[x] -> return x
|
||||||
|
[] -> Bad "no parse"
|
||||||
|
_ -> Bad "ambiguous"
|
||||||
|
|
||||||
|
(...) :: Parser a b -> Parser a c -> Parser a (b,c)
|
||||||
|
(p ... q) s = [((x,y),r) | (x,t) <- p s, (y,r) <- q t]
|
||||||
|
|
||||||
|
(.>.) :: Parser a b -> (b -> Parser a c) -> Parser a c
|
||||||
|
(p .>. f) s = [(c,r) | (x,t) <- p s, (c,r) <- f x t]
|
||||||
|
|
||||||
|
(|||) :: Parser a b -> Parser a b -> Parser a b
|
||||||
|
(p ||| q) s = p s ++ q s
|
||||||
|
|
||||||
|
(+||) :: Parser a b -> Parser a b -> Parser a b
|
||||||
|
p1 +|| p2 = take 1 . (p1 ||| p2)
|
||||||
|
|
||||||
|
literal :: (Eq a) => a -> Parser a a
|
||||||
|
literal x (c:cs) = [(x,cs) | x == c]
|
||||||
|
literal _ _ = []
|
||||||
|
|
||||||
|
(***) :: Parser a b -> (b -> c) -> Parser a c
|
||||||
|
(p *** f) s = [(f x,r) | (x,r) <- p s]
|
||||||
|
|
||||||
|
succeed :: b -> Parser a b
|
||||||
|
succeed v s = [(v,s)]
|
||||||
|
|
||||||
|
fails :: Parser a b
|
||||||
|
fails s = []
|
||||||
|
|
||||||
|
(+..) :: Parser a b -> Parser a c -> Parser a c
|
||||||
|
p1 +.. p2 = p1 ... p2 *** snd
|
||||||
|
|
||||||
|
(..+) :: Parser a b -> Parser a c -> Parser a b
|
||||||
|
p1 ..+ p2 = p1 ... p2 *** fst
|
||||||
|
|
||||||
|
(<<<) :: Parser a b -> c -> Parser a c -- return
|
||||||
|
p <<< v = p *** (\x -> v)
|
||||||
|
|
||||||
|
(|>) :: Parser a b -> (b -> Bool) -> Parser a b
|
||||||
|
p |> b = p .>. (\x -> if b x then succeed x else fails)
|
||||||
|
|
||||||
|
many :: Parser a b -> Parser a [b]
|
||||||
|
many p = (p ... many p *** uncurry (:)) +|| succeed []
|
||||||
|
|
||||||
|
some :: Parser a b -> Parser a [b]
|
||||||
|
some p = (p ... many p) *** uncurry (:)
|
||||||
|
|
||||||
|
longestOfMany :: Parser a b -> Parser a [b]
|
||||||
|
longestOfMany p = p .>. (\x -> longestOfMany p *** (x:)) +|| succeed []
|
||||||
|
|
||||||
|
closure :: (b -> Parser a b) -> (b -> Parser a b)
|
||||||
|
closure p v = p v .>. closure p ||| succeed v
|
||||||
|
|
||||||
|
pJunk :: Parser Char String
|
||||||
|
pJunk = longestOfMany (satisfy (\x -> elem x "\n\t "))
|
||||||
|
|
||||||
|
pJ :: Parser Char a -> Parser Char a
|
||||||
|
pJ p = pJunk +.. p ..+ pJunk
|
||||||
|
|
||||||
|
pTList :: String -> Parser Char a -> Parser Char [a]
|
||||||
|
pTList t p = p .... many (jL t +.. p) *** (\ (x,y) -> x:y) -- mod. AR 5/1/1999
|
||||||
|
|
||||||
|
pTJList :: String -> String -> Parser Char a -> Parser Char [a]
|
||||||
|
pTJList t1 t2 p = p .... many (literals t1 +.. jL t2 +.. p) *** (uncurry (:))
|
||||||
|
|
||||||
|
pElem :: [String] -> Parser Char String
|
||||||
|
pElem l = foldr (+||) fails (map literals l)
|
||||||
|
|
||||||
|
(....) :: Parser Char b -> Parser Char c -> Parser Char (b,c)
|
||||||
|
p1 .... p2 = p1 ... pJunk +.. p2
|
||||||
|
|
||||||
|
item :: Parser a a
|
||||||
|
item (c:cs) = [(c,cs)]
|
||||||
|
item [] = []
|
||||||
|
|
||||||
|
satisfy :: (a -> Bool) -> Parser a a
|
||||||
|
satisfy b = item |> b
|
||||||
|
|
||||||
|
literals :: (Eq a,Show a) => [a] -> Parser a [a]
|
||||||
|
literals l = case l of
|
||||||
|
[] -> succeed []
|
||||||
|
a:l -> literal a ... literals l *** (\ (x,y) -> x:y)
|
||||||
|
|
||||||
|
lits :: (Eq a,Show a) => [a] -> Parser a [a]
|
||||||
|
lits ts = literals ts
|
||||||
|
|
||||||
|
jL :: String -> Parser Char String
|
||||||
|
jL = pJ . lits
|
||||||
|
|
||||||
|
pParenth p = literal '(' +.. pJunk +.. p ..+ pJunk ..+ literal ')'
|
||||||
|
pCommaList p = pTList "," (pJ p) -- p,...,p
|
||||||
|
pOptCommaList p = pCommaList p ||| succeed [] -- the same or nothing
|
||||||
|
pArgList p = pParenth (pCommaList p) ||| succeed [] -- (p,...,p), poss. empty
|
||||||
|
pArgList2 p = pParenth (p ... jL "," +.. pCommaList p) *** uncurry (:) -- min.2 args
|
||||||
|
|
||||||
|
longestOfSome p = (p ... longestOfMany p) *** (\ (x,y) -> x:y)
|
||||||
|
|
||||||
|
pIdent = pLetter ... longestOfMany pAlphaPlusChar *** uncurry (:)
|
||||||
|
where alphaPlusChar c = isAlphaNum c || c=='_' || c=='\''
|
||||||
|
|
||||||
|
pLetter = satisfy (`elem` (['A'..'Z'] ++ ['a'..'z'] ++
|
||||||
|
['À' .. 'Û'] ++ ['à' .. 'û'])) -- no such in Char
|
||||||
|
pDigit = satisfy isDigit
|
||||||
|
pLetters = longestOfSome pLetter
|
||||||
|
pAlphanum = pDigit ||| pLetter
|
||||||
|
pAlphaPlusChar = pAlphanum ||| satisfy (`elem` "_'")
|
||||||
|
|
||||||
|
pQuotedString = literal '"' +.. pEndQuoted where
|
||||||
|
pEndQuoted =
|
||||||
|
literal '"' *** (const [])
|
||||||
|
+|| (literal '\\' +.. item .>. \ c -> pEndQuoted *** (c:))
|
||||||
|
+|| item .>. \ c -> pEndQuoted *** (c:)
|
||||||
|
|
||||||
|
pIntc :: Parser Char Int
|
||||||
|
pIntc = some (satisfy numb) *** read
|
||||||
|
where numb x = elem x ['0'..'9']
|
||||||
|
|
||||||
106
src/GF/Data/Str.hs
Normal file
106
src/GF/Data/Str.hs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
module Str (
|
||||||
|
Str (..), Tok (..), --- constructors needed in PrGrammar
|
||||||
|
str2strings, str2allStrings, str, sstr, sstrV,
|
||||||
|
isZeroTok, prStr, plusStr, glueStr,
|
||||||
|
strTok,
|
||||||
|
allItems
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import List (isPrefixOf, isSuffixOf, intersperse)
|
||||||
|
|
||||||
|
-- abstract token list type. AR 2001, revised and simplified 20/4/2003
|
||||||
|
|
||||||
|
newtype Str = Str [Tok] deriving (Read, Show, Eq, Ord)
|
||||||
|
|
||||||
|
data Tok =
|
||||||
|
TK String
|
||||||
|
| TN Ss [(Ss, [String])] -- variants depending on next string
|
||||||
|
deriving (Eq, Ord, Show, Read)
|
||||||
|
|
||||||
|
-- notice that having both pre and post would leave to inconsistent situations:
|
||||||
|
-- pre {"x" ; "y" / "a"} ++ post {"b" ; "a" / "x"}
|
||||||
|
-- always violates a condition expressed by the one or the other
|
||||||
|
|
||||||
|
-- a variant can itself be a token list, but for simplicity only a list of strings
|
||||||
|
-- i.e. not itself containing variants
|
||||||
|
|
||||||
|
type Ss = [String]
|
||||||
|
|
||||||
|
-- matching functions in both ways
|
||||||
|
|
||||||
|
matchPrefix :: Ss -> [(Ss,[String])] -> [String] -> Ss
|
||||||
|
matchPrefix s vs t =
|
||||||
|
head ([u | (u,as) <- vs, any (\c -> isPrefixOf c (concat t)) as] ++ [s])
|
||||||
|
|
||||||
|
str2strings :: Str -> Ss
|
||||||
|
str2strings (Str st) = alls st where
|
||||||
|
alls st = case st of
|
||||||
|
TK s : ts -> s : alls ts
|
||||||
|
TN ds vs : ts -> matchPrefix ds vs t ++ t where t = alls ts
|
||||||
|
[] -> []
|
||||||
|
|
||||||
|
str2allStrings :: Str -> [Ss]
|
||||||
|
str2allStrings (Str st) = alls st where
|
||||||
|
alls st = case st of
|
||||||
|
TK s : ts -> [s : t | t <- alls ts]
|
||||||
|
TN ds vs : [] -> [ds ++ v | v <- map fst vs]
|
||||||
|
TN ds vs : ts -> [matchPrefix ds vs t ++ t | t <- alls ts]
|
||||||
|
[] -> [[]]
|
||||||
|
|
||||||
|
sstr :: Str -> String
|
||||||
|
sstr = unwords . str2strings
|
||||||
|
|
||||||
|
-- to handle a list of variants
|
||||||
|
|
||||||
|
sstrV :: [Str] -> String
|
||||||
|
sstrV ss = case ss of
|
||||||
|
[] -> "*"
|
||||||
|
_ -> unwords $ intersperse "/" $ map (unwords . str2strings) ss
|
||||||
|
|
||||||
|
str :: String -> Str
|
||||||
|
str s = if null s then Str [] else Str [itS s]
|
||||||
|
|
||||||
|
itS :: String -> Tok
|
||||||
|
itS s = TK s
|
||||||
|
|
||||||
|
isZeroTok :: Str -> Bool
|
||||||
|
isZeroTok t = case t of
|
||||||
|
Str [] -> True
|
||||||
|
Str [TK []] -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
strTok :: Ss -> [(Ss,[String])] -> Str
|
||||||
|
strTok ds vs = Str [TN ds vs]
|
||||||
|
|
||||||
|
prStr = prQuotedString . sstr
|
||||||
|
|
||||||
|
plusStr :: Str -> Str -> Str
|
||||||
|
plusStr (Str ss) (Str tt) = Str (ss ++ tt)
|
||||||
|
|
||||||
|
glueStr :: Str -> Str -> Str
|
||||||
|
glueStr (Str ss) (Str tt) = Str $ case (ss,tt) of
|
||||||
|
([],_) -> tt
|
||||||
|
(_,[]) -> ss
|
||||||
|
_ -> init ss ++ glueIt (last ss) (head tt) ++ tail tt
|
||||||
|
where
|
||||||
|
glueIt t u = case (t,u) of
|
||||||
|
(TK s, TK s') -> return $ TK $ s ++ s'
|
||||||
|
(TN ds vs, TN es ws) -> return $ TN (glues (matchPrefix ds vs es) es)
|
||||||
|
[(glues (matchPrefix ds vs w) w,cs) | (w,cs) <- ws]
|
||||||
|
(TN ds vs, TK s) -> map TK $ glues (matchPrefix ds vs [s]) [s]
|
||||||
|
(TK s, TN es ws) -> return $ TN (glues [s] es) [(glues [s] w, c) | (w,c) <- ws]
|
||||||
|
|
||||||
|
glues :: [[a]] -> [[a]] -> [[a]]
|
||||||
|
glues ss tt = case (ss,tt) of
|
||||||
|
([],_) -> tt
|
||||||
|
(_,[]) -> ss
|
||||||
|
_ -> init ss ++ [last ss ++ head tt] ++ tail tt
|
||||||
|
|
||||||
|
-- to create the list of all lexical items
|
||||||
|
|
||||||
|
allItems :: Str -> [String]
|
||||||
|
allItems (Str s) = concatMap allOne s where
|
||||||
|
allOne t = case t of
|
||||||
|
TK s -> [s]
|
||||||
|
TN ds vs -> ds ++ concatMap fst vs
|
||||||
172
src/GF/Data/Zipper.hs
Normal file
172
src/GF/Data/Zipper.hs
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
module Zipper where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
-- Gérard Huet's zipper (JFP 7 (1997)). AR 10/8/2001
|
||||||
|
|
||||||
|
newtype Tr a = Tr (a,[Tr a]) deriving (Show,Eq)
|
||||||
|
|
||||||
|
data Path a =
|
||||||
|
Top
|
||||||
|
| Node ([Tr a], (Path a, a), [Tr a])
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
leaf a = Tr (a,[])
|
||||||
|
|
||||||
|
newtype Loc a = Loc (Tr a, Path a) deriving Show
|
||||||
|
|
||||||
|
goLeft, goRight, goUp, goDown :: Loc a -> Err (Loc a)
|
||||||
|
goLeft (Loc (t,p)) = case p of
|
||||||
|
Top -> Bad "left of top"
|
||||||
|
Node (l:left, upv, right) -> return $ Loc (l, Node (left,upv,t:right))
|
||||||
|
Node _ -> Bad "left of first"
|
||||||
|
goRight (Loc (t,p)) = case p of
|
||||||
|
Top -> Bad "right of top"
|
||||||
|
Node (left, upv, r:right) -> return $ Loc (r, Node (t:left,upv,right))
|
||||||
|
Node _ -> Bad "right of first"
|
||||||
|
goUp (Loc (t,p)) = case p of
|
||||||
|
Top -> Bad "up of top"
|
||||||
|
Node (left, (up,v), right) ->
|
||||||
|
return $ Loc (Tr (v, reverse left ++ (t:right)), up)
|
||||||
|
goDown (Loc (t,p)) = case t of
|
||||||
|
Tr (v,(t1:trees)) -> return $ Loc (t1,Node ([],(p,v),trees))
|
||||||
|
_ -> Bad "down of empty"
|
||||||
|
|
||||||
|
changeLoc :: Loc a -> Tr a -> Err (Loc a)
|
||||||
|
changeLoc (Loc (_,p)) t = return $ Loc (t,p)
|
||||||
|
|
||||||
|
changeNode :: (a -> a) -> Loc a -> Loc a
|
||||||
|
changeNode f (Loc (Tr (n,ts),p)) = Loc (Tr (f n, ts),p)
|
||||||
|
|
||||||
|
forgetNode :: Loc a -> Err (Loc a)
|
||||||
|
forgetNode (Loc (Tr (n,[t]),p)) = return $ Loc (t,p)
|
||||||
|
forgetNode _ = Bad $ "not a one-branch tree"
|
||||||
|
|
||||||
|
-- added sequential representation
|
||||||
|
|
||||||
|
-- a successor function
|
||||||
|
goAhead :: Loc a -> Err (Loc a)
|
||||||
|
goAhead s@(Loc (t,p)) = case (t,p) of
|
||||||
|
(Tr (_,_:_),Node (_,_,_:_)) -> goDown s
|
||||||
|
(Tr (_,[]), _) -> upsRight s
|
||||||
|
(_, _) -> goDown s
|
||||||
|
where
|
||||||
|
upsRight t = case goRight t of
|
||||||
|
Ok t' -> return t'
|
||||||
|
Bad _ -> goUp t >>= upsRight
|
||||||
|
|
||||||
|
-- a predecessor function
|
||||||
|
goBack :: Loc a -> Err (Loc a)
|
||||||
|
goBack s@(Loc (t,p)) = case goLeft s of
|
||||||
|
Ok s' -> downRight s'
|
||||||
|
_ -> goUp s
|
||||||
|
where
|
||||||
|
downRight s = case goDown s of
|
||||||
|
Ok s' -> case goRight s' of
|
||||||
|
Ok s'' -> downRight s''
|
||||||
|
_ -> downRight s'
|
||||||
|
_ -> return s
|
||||||
|
|
||||||
|
-- n-ary versions
|
||||||
|
|
||||||
|
goAheadN :: Int -> Loc a -> Err (Loc a)
|
||||||
|
goAheadN i st
|
||||||
|
| i < 1 = return st
|
||||||
|
| otherwise = goAhead st >>= goAheadN (i-1)
|
||||||
|
|
||||||
|
goBackN :: Int -> Loc a -> Err (Loc a)
|
||||||
|
goBackN i st
|
||||||
|
| i < 1 = return st
|
||||||
|
| otherwise = goBack st >>= goBackN (i-1)
|
||||||
|
|
||||||
|
-- added mappings between locations and trees
|
||||||
|
|
||||||
|
loc2tree (Loc (t,p)) = case p of
|
||||||
|
Top -> t
|
||||||
|
Node (left,(p',v),right) ->
|
||||||
|
loc2tree (Loc (Tr (v, reverse left ++ (t : right)),p'))
|
||||||
|
|
||||||
|
loc2treeMarked :: Loc a -> Tr (a, Bool)
|
||||||
|
loc2treeMarked (Loc (Tr (a,ts),p)) =
|
||||||
|
loc2tree (Loc (Tr (mark a, map (mapTr nomark) ts), mapPath nomark p))
|
||||||
|
where
|
||||||
|
(mark, nomark) = (\a -> (a,True), \a -> (a, False))
|
||||||
|
|
||||||
|
tree2loc t = Loc (t,Top)
|
||||||
|
|
||||||
|
goRoot = tree2loc . loc2tree
|
||||||
|
|
||||||
|
goLast :: Loc a -> Err (Loc a)
|
||||||
|
goLast = rep goAhead where
|
||||||
|
rep f s = err (const (return s)) (rep f) (f s)
|
||||||
|
|
||||||
|
-- added some utilities
|
||||||
|
|
||||||
|
traverseCollect :: Path a -> [a]
|
||||||
|
traverseCollect p = reverse $ case p of
|
||||||
|
Top -> []
|
||||||
|
Node (_, (p',v), _) -> v : traverseCollect p'
|
||||||
|
|
||||||
|
scanTree :: Tr a -> [a]
|
||||||
|
scanTree (Tr (a,ts)) = a : concatMap scanTree ts
|
||||||
|
|
||||||
|
mapTr :: (a -> b) -> Tr a -> Tr b
|
||||||
|
mapTr f (Tr (x,ts)) = Tr (f x, map (mapTr f) ts)
|
||||||
|
|
||||||
|
mapTrM :: Monad m => (a -> m b) -> Tr a -> m (Tr b)
|
||||||
|
mapTrM f (Tr (x,ts)) = do
|
||||||
|
fx <- f x
|
||||||
|
fts <- mapM (mapTrM f) ts
|
||||||
|
return $ Tr (fx,fts)
|
||||||
|
|
||||||
|
mapPath :: (a -> b) -> Path a -> Path b
|
||||||
|
mapPath f p = case p of
|
||||||
|
Node (ts1, (p,v), ts2) ->
|
||||||
|
Node (map (mapTr f) ts1, (mapPath f p, f v), map (mapTr f) ts2)
|
||||||
|
Top -> Top
|
||||||
|
|
||||||
|
mapPathM :: Monad m => (a -> m b) -> Path a -> m (Path b)
|
||||||
|
mapPathM f p = case p of
|
||||||
|
Node (ts1, (p,v), ts2) -> do
|
||||||
|
ts1' <- mapM (mapTrM f) ts1
|
||||||
|
p' <- mapPathM f p
|
||||||
|
v' <- f v
|
||||||
|
ts2' <- mapM (mapTrM f) ts2
|
||||||
|
return $ Node (ts1', (p',v'), ts2')
|
||||||
|
Top -> return Top
|
||||||
|
|
||||||
|
mapLoc :: (a -> b) -> Loc a -> Loc b
|
||||||
|
mapLoc f (Loc (t,p)) = Loc (mapTr f t, mapPath f p)
|
||||||
|
|
||||||
|
mapLocM :: Monad m => (a -> m b) -> Loc a -> m (Loc b)
|
||||||
|
mapLocM f (Loc (t,p)) = do
|
||||||
|
t' <- mapTrM f t
|
||||||
|
p' <- mapPathM f p
|
||||||
|
return $ (Loc (t',p'))
|
||||||
|
|
||||||
|
foldTr :: (a -> [b] -> b) -> Tr a -> b
|
||||||
|
foldTr f (Tr (x,ts)) = f x (map (foldTr f) ts)
|
||||||
|
|
||||||
|
foldTrM :: Monad m => (a -> [b] -> m b) -> Tr a -> m b
|
||||||
|
foldTrM f (Tr (x,ts)) = do
|
||||||
|
fts <- mapM (foldTrM f) ts
|
||||||
|
f x fts
|
||||||
|
|
||||||
|
mapSubtrees :: (Tr a -> Tr a) -> Tr a -> Tr a
|
||||||
|
mapSubtrees f t = let Tr (x,ts) = f t in Tr (x, map (mapSubtrees f) ts)
|
||||||
|
|
||||||
|
mapSubtreesM :: Monad m => (Tr a -> m (Tr a)) -> Tr a -> m (Tr a)
|
||||||
|
mapSubtreesM f t = do
|
||||||
|
Tr (x,ts) <- f t
|
||||||
|
ts' <- mapM (mapSubtreesM f) ts
|
||||||
|
return $ Tr (x, ts')
|
||||||
|
|
||||||
|
-- change the root without moving the pointer
|
||||||
|
changeRoot :: (a -> a) -> Loc a -> Loc a
|
||||||
|
changeRoot f loc = case loc of
|
||||||
|
Loc (Tr (a,ts),Top) -> Loc (Tr (f a,ts),Top)
|
||||||
|
Loc (t, Node (left,pv,right)) -> Loc (t, Node (left,chPath pv,right))
|
||||||
|
where
|
||||||
|
chPath pv = case pv of
|
||||||
|
(Top,a) -> (Top, f a)
|
||||||
|
(Node (left,pv,right),v) -> (Node (left, chPath pv,right),v)
|
||||||
16
src/GF/Fudgets/ArchEdit.hs
Normal file
16
src/GF/Fudgets/ArchEdit.hs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
module ArchEdit (
|
||||||
|
fudlogueEdit, fudlogueWrite, fudlogueWriteUni
|
||||||
|
) where
|
||||||
|
|
||||||
|
import CommandF
|
||||||
|
import UnicodeF
|
||||||
|
|
||||||
|
-- architecture/compiler dependent definitions for unix/ghc, if Fudgets works.
|
||||||
|
-- If not, use the modules in for-ghci
|
||||||
|
|
||||||
|
fudlogueEdit font = fudlogueEditF ----
|
||||||
|
fudlogueWrite = fudlogueWriteU
|
||||||
|
fudlogueWriteUni _ _ = do
|
||||||
|
putStrLn "sorry no unicode available in ghc"
|
||||||
|
|
||||||
|
|
||||||
120
src/GF/Fudgets/CommandF.hs
Normal file
120
src/GF/Fudgets/CommandF.hs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
module CommandF where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Session
|
||||||
|
import Commands
|
||||||
|
|
||||||
|
import Fudgets
|
||||||
|
import FudgetOps
|
||||||
|
|
||||||
|
import EventF
|
||||||
|
|
||||||
|
-- a graphical shell for any kind of GF with Zipper editing. AR 20/8/2001
|
||||||
|
|
||||||
|
fudlogueEditF :: CEnv -> IO ()
|
||||||
|
fudlogueEditF env =
|
||||||
|
fudlogue $ gfSizeP $ shellF ("GF 1.1 Fudget Editor") (gfF env)
|
||||||
|
|
||||||
|
gfF env = nameLayoutF gfLayout $ (gfOutputF env >==< gfCommandF env) >+< quitButF
|
||||||
|
|
||||||
|
( quitN : menusN : newN : transformN : filterN : displayN :
|
||||||
|
navigateN : viewN : outputN : saveN : _) = map show [1..]
|
||||||
|
|
||||||
|
gfLayout = placeNL verticalP [generics,output,navigate,menus,transform]
|
||||||
|
where
|
||||||
|
generics = placeNL horizontalP (map leafNL
|
||||||
|
[newN,saveN,viewN,displayN,filterN,quitN])
|
||||||
|
output = leafNL outputN
|
||||||
|
navigate = leafNL navigateN
|
||||||
|
menus = leafNL menusN
|
||||||
|
transform = leafNL transformN
|
||||||
|
|
||||||
|
gfSizeP = spacerF (sizeS (Point 720 640))
|
||||||
|
|
||||||
|
gfOutputF env =
|
||||||
|
((nameF outputN $ (writeFileF >+< textWindowF))
|
||||||
|
>==<
|
||||||
|
(absF (saveSP "EMPTY")
|
||||||
|
>==<
|
||||||
|
(nameF saveN (popupStringInputF "Save" "foo.tmp" "Save to file:")
|
||||||
|
>+<
|
||||||
|
mapF (displayJustStateIn env))))
|
||||||
|
>==<
|
||||||
|
mapF Right
|
||||||
|
|
||||||
|
gfCommandF :: CEnv -> F () SState
|
||||||
|
gfCommandF env = loopCommandsF env >==< getCommandsF env >==< mapF (\_ -> Click)
|
||||||
|
|
||||||
|
loopCommandsF :: CEnv -> F Command SState
|
||||||
|
loopCommandsF env = loopThroughRightF (mapGfStateF env) (mkMenusF env)
|
||||||
|
|
||||||
|
mapGfStateF :: CEnv -> F (Either Command Command) (Either SState SState)
|
||||||
|
mapGfStateF env = mapstateF execFC (initSState) where
|
||||||
|
execFC e0 (Left c) = (e,[Right e,Left e]) where e = execECommand env c e0
|
||||||
|
execFC e0 (Right c) = (e,[Left e,Right e]) where e = execECommand env c e0
|
||||||
|
|
||||||
|
mkMenusF :: CEnv -> F SState Command
|
||||||
|
mkMenusF env =
|
||||||
|
nameF menusN $
|
||||||
|
labAboveF "Select Action on Subterm"
|
||||||
|
(mapF fst >==< smallPickListF snd >==< mapF (mkRefineMenu env))
|
||||||
|
|
||||||
|
getCommandsF env =
|
||||||
|
newF env >*<
|
||||||
|
viewF >*<
|
||||||
|
menuDisplayF env >*<
|
||||||
|
filterF >*<
|
||||||
|
navigateF >*<
|
||||||
|
transformF
|
||||||
|
|
||||||
|
key2command ((key,_),_) = case key of
|
||||||
|
"Up" -> CBack 1
|
||||||
|
"Down" -> CAhead 1
|
||||||
|
"Left" -> CPrevMeta
|
||||||
|
"Right" -> CNextMeta
|
||||||
|
"space" -> CTop
|
||||||
|
|
||||||
|
"d" -> CDelete
|
||||||
|
"u" -> CUndo
|
||||||
|
"v" -> CView
|
||||||
|
|
||||||
|
_ -> CVoid
|
||||||
|
|
||||||
|
transformF =
|
||||||
|
nameF transformN $
|
||||||
|
mapF (either key2command id) >==< (keyboardF $
|
||||||
|
placerF horizontalP $
|
||||||
|
cPopupStringInputF CRefineParse "Parse" "" "Parse in concrete syntax" >*<
|
||||||
|
--- to enable Unicode: ("Refine by parsing" `labLeftOfF` writeInputF)
|
||||||
|
cPopupStringInputF CRefineWithTree "Term" "" "Parse term" >*<
|
||||||
|
cMenuF "Modify" termCommandMenu >*<
|
||||||
|
cPopupStringInputF CAlphaConvert "Alpha" "x_0 x" "Alpha convert" >*<
|
||||||
|
cButtonF CRefineRandom "Random" >*<
|
||||||
|
cButtonF CUndo "Undo"
|
||||||
|
)
|
||||||
|
|
||||||
|
quitButF = nameF quitN $ quitF >==< buttonF "Quit"
|
||||||
|
|
||||||
|
newF env = nameF newN $ cMenuF "New" (newCatMenu env)
|
||||||
|
menuDisplayF env = nameF displayN $ cMenuF "Menus" $ displayCommandMenu env
|
||||||
|
filterF = nameF filterN $ cMenuF "Filter" stringCommandMenu
|
||||||
|
|
||||||
|
viewF = nameF viewN $ cButtonF CView "View"
|
||||||
|
|
||||||
|
navigateF =
|
||||||
|
nameF navigateN $
|
||||||
|
placerF horizontalP $
|
||||||
|
cButtonF CPrevMeta "?<" >*<
|
||||||
|
cButtonF (CBack 1) "<" >*<
|
||||||
|
cButtonF CTop "Top" >*<
|
||||||
|
cButtonF CLast "Last" >*<
|
||||||
|
cButtonF (CAhead 1) ">" >*<
|
||||||
|
cButtonF CNextMeta ">?"
|
||||||
|
|
||||||
|
cButtonF c s = mapF (const c) >==< buttonF s
|
||||||
|
cMenuF s css = menuF s css >==< mapF (\_ -> CVoid)
|
||||||
|
|
||||||
|
cPopupStringInputF comm lab def msg =
|
||||||
|
mapF comm >==< popupStringInputF lab def msg >==< mapF (const [])
|
||||||
|
|
||||||
36
src/GF/Fudgets/EventF.hs
Normal file
36
src/GF/Fudgets/EventF.hs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
module EventF where
|
||||||
|
import AllFudgets
|
||||||
|
|
||||||
|
-- The first string is the name of the key (e.g., "Down" for the down arrow key)
|
||||||
|
-- The modifiers list shift, control and alt keys that were active while the
|
||||||
|
-- key was pressed.
|
||||||
|
-- The last string is the text produced by the key (for keys that produce
|
||||||
|
-- printable characters, empty for control keys).
|
||||||
|
|
||||||
|
type KeyPress = ((String,[Modifiers]),String)
|
||||||
|
|
||||||
|
keyboardF :: F i o -> F i (Either KeyPress o)
|
||||||
|
keyboardF fud = idRightSP (concatMapSP post) >^^=< oeventF mask fud
|
||||||
|
where
|
||||||
|
post (KeyEvent {type'=Pressed,keySym=sym,state=mods,keyLookup=s}) =
|
||||||
|
[((sym,mods),s)]
|
||||||
|
post _ = []
|
||||||
|
|
||||||
|
mask = [KeyPressMask,
|
||||||
|
EnterWindowMask, LeaveWindowMask -- because of CTT implementation
|
||||||
|
]
|
||||||
|
|
||||||
|
-- Output events:
|
||||||
|
oeventF em fud = eventF em (idLeftF fud)
|
||||||
|
|
||||||
|
-- Feed events to argument fudget:
|
||||||
|
eventF eventmask = serCompLeftToRightF . groupF startcmds eventK
|
||||||
|
where
|
||||||
|
startcmds = [XCmd $ ChangeWindowAttributes [CWEventMask eventmask],
|
||||||
|
XCmd $ ConfigureWindow [CWBorderWidth 0]]
|
||||||
|
eventK = K $ mapFilterSP route
|
||||||
|
where route = message low high
|
||||||
|
low (XEvt event) = Just (High (Left event))
|
||||||
|
low _ = Nothing
|
||||||
|
high h = Just (High (Right h))
|
||||||
|
|
||||||
47
src/GF/Fudgets/FudgetOps.hs
Normal file
47
src/GF/Fudgets/FudgetOps.hs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
module FudgetOps where
|
||||||
|
|
||||||
|
import Fudgets
|
||||||
|
|
||||||
|
-- auxiliary Fudgets for GF syntax editor
|
||||||
|
|
||||||
|
-- save and display
|
||||||
|
|
||||||
|
showAndSaveF fud = (writeFileF >+< textWindowF) >==< saveF fud
|
||||||
|
|
||||||
|
saveF :: F a String -> F (Either String a) (Either (String,String) String)
|
||||||
|
saveF fud =
|
||||||
|
absF (saveSP "EMPTY")
|
||||||
|
>==<
|
||||||
|
(popupStringInputF "Save" "foo.tmp" "Save to file:" >+< fud)
|
||||||
|
|
||||||
|
saveSP :: String -> SP (Either String String) (Either (String,String) String)
|
||||||
|
saveSP contents = getSP $ \msg -> case msg of
|
||||||
|
Left file -> putSP (Left (file,contents)) (saveSP contents)
|
||||||
|
Right string -> putSP (Right string) (saveSP string)
|
||||||
|
|
||||||
|
textWindowF = writeOutputF
|
||||||
|
|
||||||
|
-- to replace stringInputF by a pop-up slot behind a button
|
||||||
|
popupStringInputF :: String -> String -> String -> F String String
|
||||||
|
popupStringInputF label deflt msg =
|
||||||
|
mapF snd
|
||||||
|
>==<
|
||||||
|
(popupSizeP $ stringPopupF deflt)
|
||||||
|
>==<
|
||||||
|
mapF (\_ -> (Just msg,Nothing))
|
||||||
|
>==<
|
||||||
|
decentButtonF label
|
||||||
|
>==<
|
||||||
|
mapF (\_ -> Click)
|
||||||
|
|
||||||
|
decentButtonF = spacerF (sizeS (Point 80 20)) . buttonF
|
||||||
|
|
||||||
|
popupSizeP = spacerF (sizeS (Point 240 100))
|
||||||
|
|
||||||
|
--- the Unicode stuff should be inserted here
|
||||||
|
|
||||||
|
writeOutputF = moreF >==< mapF lines
|
||||||
|
|
||||||
|
writeInputF = stringInputF
|
||||||
|
|
||||||
|
|
||||||
23
src/GF/Fudgets/UnicodeF.hs
Normal file
23
src/GF/Fudgets/UnicodeF.hs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
module UnicodeF where
|
||||||
|
import Fudgets
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Unicode
|
||||||
|
|
||||||
|
-- AR 12/4/2000, 18/9/2001 (added font parameter)
|
||||||
|
|
||||||
|
fudlogueWriteU :: String -> (String -> String) -> IO ()
|
||||||
|
fudlogueWriteU fn trans =
|
||||||
|
fudlogue $
|
||||||
|
shellF "GF Unicode Output" (writeF fn trans >+< quitButtonF)
|
||||||
|
|
||||||
|
writeF fn trans = writeOutputF fn >==< mapF trans >==< writeInputF fn
|
||||||
|
|
||||||
|
displaySizeP = placerF (spacerP (sizeS (Point 440 500)) verticalP)
|
||||||
|
|
||||||
|
writeOutputF fn = moreF' (setFont fn) >==< justWriteOutputF
|
||||||
|
|
||||||
|
justWriteOutputF = mapF (map (wrapLines 0) . filter (/=[]) . map mkUnicode . lines)
|
||||||
|
|
||||||
|
writeInputF fn = stringInputF' (setShowString mkUnicode . setFont fn)
|
||||||
|
|
||||||
64
src/GF/Grammar/AbsCompute.hs
Normal file
64
src/GF/Grammar/AbsCompute.hs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
module AbsCompute where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
import Abstract
|
||||||
|
import PrGrammar
|
||||||
|
import LookAbs
|
||||||
|
import PatternMatch
|
||||||
|
import Compute
|
||||||
|
|
||||||
|
import Monad (liftM, liftM2)
|
||||||
|
|
||||||
|
-- computation in abstract syntax w.r.t. explicit definitions.
|
||||||
|
--- old GF computation; to be updated
|
||||||
|
|
||||||
|
compute :: GFCGrammar -> Exp -> Err Exp
|
||||||
|
compute = computeAbsTerm
|
||||||
|
|
||||||
|
computeAbsTerm :: GFCGrammar -> Exp -> Err Exp
|
||||||
|
computeAbsTerm gr = computeAbsTermIn gr []
|
||||||
|
|
||||||
|
computeAbsTermIn :: GFCGrammar -> [Ident] -> Exp -> Err Exp
|
||||||
|
computeAbsTermIn gr = compt where
|
||||||
|
compt vv t = case t of
|
||||||
|
Prod x a b -> liftM2 (Prod x) (compt vv a) (compt (x:vv) b)
|
||||||
|
Abs x b -> liftM (Abs x) (compt (x:vv) b)
|
||||||
|
_ -> do
|
||||||
|
let t' = beta vv t
|
||||||
|
(yy,f,aa) <- termForm t'
|
||||||
|
let vv' = yy ++ vv
|
||||||
|
aa' <- mapM (compt vv') aa
|
||||||
|
case look f of
|
||||||
|
Just (Eqs eqs) -> case findMatch eqs aa' of
|
||||||
|
Ok (d,g) -> do
|
||||||
|
let (xs,ts) = unzip g
|
||||||
|
ts' <- alphaFreshAll vv' ts ---
|
||||||
|
let g' = zip xs ts'
|
||||||
|
d' <- compt vv' $ substTerm vv' g' d
|
||||||
|
return $ mkAbs yy $ d'
|
||||||
|
_ -> do
|
||||||
|
return $ mkAbs yy $ mkApp f aa'
|
||||||
|
Just d -> do
|
||||||
|
d' <- compt vv' d
|
||||||
|
da <- ifNull (return d') (compt vv' . mkApp d') aa'
|
||||||
|
return $ mkAbs yy $ da
|
||||||
|
_ -> do
|
||||||
|
return $ mkAbs yy $ mkApp f aa'
|
||||||
|
|
||||||
|
look (Q m f) = case lookupAbsDef gr m f of
|
||||||
|
Ok (Just (Eqs [])) -> Nothing -- canonical
|
||||||
|
Ok md -> md
|
||||||
|
_ -> Nothing
|
||||||
|
look _ = Nothing
|
||||||
|
|
||||||
|
beta :: [Ident] -> Exp -> Exp
|
||||||
|
beta vv c = case c of
|
||||||
|
App (Abs x b) a -> beta vv $ substTerm vv [xvv] (beta (x:vv) b)
|
||||||
|
where xvv = (x,beta vv a)
|
||||||
|
App f a -> let (a',f') = (beta vv a, beta vv f) in
|
||||||
|
(if a'==a && f'==f then id else beta vv) $ App f' a'
|
||||||
|
Prod x a b -> Prod x (beta vv a) (beta (x:vv) b)
|
||||||
|
Abs x b -> Abs x (beta (x:vv) b)
|
||||||
|
_ -> c
|
||||||
|
|
||||||
24
src/GF/Grammar/Abstract.hs
Normal file
24
src/GF/Grammar/Abstract.hs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
module Abstract (
|
||||||
|
|
||||||
|
module Grammar,
|
||||||
|
module Values,
|
||||||
|
module Macros,
|
||||||
|
module Ident,
|
||||||
|
module MMacros,
|
||||||
|
module PrGrammar,
|
||||||
|
|
||||||
|
Grammar
|
||||||
|
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import Values
|
||||||
|
import Macros
|
||||||
|
import Ident
|
||||||
|
import MMacros
|
||||||
|
import PrGrammar
|
||||||
|
|
||||||
|
type Grammar = SourceGrammar ---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
51
src/GF/Grammar/AppPredefined.hs
Normal file
51
src/GF/Grammar/AppPredefined.hs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
module AppPredefined where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import PrGrammar (prt)
|
||||||
|
---- import PGrammar (pTrm)
|
||||||
|
|
||||||
|
-- predefined function definitions. AR 12/3/2003.
|
||||||
|
-- Type checker looks at signatures in predefined.gf
|
||||||
|
|
||||||
|
appPredefined :: Term -> Term
|
||||||
|
appPredefined t = case t of
|
||||||
|
|
||||||
|
App f x -> case f of
|
||||||
|
|
||||||
|
-- one-place functions
|
||||||
|
Q (IC "Predef") (IC f) -> case (f, appPredefined x) of
|
||||||
|
("length", K s) -> EInt $ length s
|
||||||
|
_ -> t
|
||||||
|
|
||||||
|
-- two-place functions
|
||||||
|
App (Q (IC "Predef") (IC f)) z -> case (f, appPredefined z, appPredefined x) of
|
||||||
|
("drop", EInt i, K s) -> K (drop i s)
|
||||||
|
("take", EInt i, K s) -> K (take i s)
|
||||||
|
("tk", EInt i, K s) -> K (take (max 0 (length s - i)) s)
|
||||||
|
("dp", EInt i, K s) -> K (drop (max 0 (length s - i)) s)
|
||||||
|
("eqStr",K s, K t) -> if s == t then predefTrue else predefFalse
|
||||||
|
("eqInt",EInt i, EInt j) -> if i==j then predefTrue else predefFalse
|
||||||
|
("plus", EInt i, EInt j) -> EInt $ i+j
|
||||||
|
("show", _, t) -> K $ prt t
|
||||||
|
("read", _, K s) -> str2tag s --- because of K, only works for atomic tags
|
||||||
|
_ -> t
|
||||||
|
_ -> t
|
||||||
|
_ -> t
|
||||||
|
|
||||||
|
-- read makes variables into constants
|
||||||
|
|
||||||
|
str2tag :: String -> Term
|
||||||
|
str2tag s = case s of
|
||||||
|
---- '\'' : cs -> mkCn $ pTrm $ init cs
|
||||||
|
_ -> Cn $ IC s ---
|
||||||
|
where
|
||||||
|
mkCn t = case t of
|
||||||
|
Vr i -> Cn i
|
||||||
|
App c a -> App (mkCn c) (mkCn a)
|
||||||
|
_ -> t
|
||||||
|
|
||||||
|
|
||||||
|
predefTrue = Q (IC "Predef") (IC "PTrue")
|
||||||
|
predefFalse = Q (IC "Predef") (IC "PFalse")
|
||||||
238
src/GF/Grammar/Compute.hs
Normal file
238
src/GF/Grammar/Compute.hs
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
module Compute where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Grammar
|
||||||
|
import Ident
|
||||||
|
import Str
|
||||||
|
import PrGrammar
|
||||||
|
import Modules
|
||||||
|
import Macros
|
||||||
|
import Lookup
|
||||||
|
import Refresh
|
||||||
|
import PatternMatch
|
||||||
|
|
||||||
|
import AppPredefined
|
||||||
|
|
||||||
|
import List (nub,intersperse)
|
||||||
|
import Monad (liftM2, liftM)
|
||||||
|
|
||||||
|
-- computation of concrete syntax terms into normal form
|
||||||
|
-- used mainly for partial evaluation
|
||||||
|
|
||||||
|
computeConcrete :: SourceGrammar -> Term -> Err Term
|
||||||
|
computeConcrete g t = {- refreshTerm t >>= -} computeTerm g [] t
|
||||||
|
|
||||||
|
computeTerm :: SourceGrammar -> Substitution -> Term -> Err Term
|
||||||
|
computeTerm gr = comp where
|
||||||
|
|
||||||
|
comp g t = --- errIn ("subterm" +++ prt t) $ --- for debugging
|
||||||
|
case t of
|
||||||
|
|
||||||
|
Q (IC "Predef") _ -> return t
|
||||||
|
Q p c -> look p c
|
||||||
|
|
||||||
|
-- if computed do nothing
|
||||||
|
Computed t' -> return $ unComputed t'
|
||||||
|
|
||||||
|
Vr x -> do
|
||||||
|
t' <- maybe (prtBad ("no value given to variable") x) return $ lookup x g
|
||||||
|
case t' of
|
||||||
|
_ | t == t' -> return t
|
||||||
|
_ -> comp g t'
|
||||||
|
|
||||||
|
Abs x b -> do
|
||||||
|
b' <- comp (ext x (Vr x) g) b
|
||||||
|
return $ Abs x b'
|
||||||
|
|
||||||
|
Let (x,(_,a)) b -> do
|
||||||
|
a' <- comp g a
|
||||||
|
comp (ext x a' g) b
|
||||||
|
|
||||||
|
Prod x a b -> do
|
||||||
|
a' <- comp g a
|
||||||
|
b' <- comp (ext x (Vr x) g) b
|
||||||
|
return $ Prod x a' b'
|
||||||
|
|
||||||
|
-- beta-convert
|
||||||
|
App f a -> do
|
||||||
|
f' <- comp g f
|
||||||
|
a' <- comp g a
|
||||||
|
case (f',a') of
|
||||||
|
(Abs x b,_) -> comp (ext x a' g) b
|
||||||
|
(FV fs, _) -> mapM (\c -> comp g (App c a')) fs >>= return . FV
|
||||||
|
(_, FV as) -> mapM (\c -> comp g (App f' c)) as >>= return . FV
|
||||||
|
|
||||||
|
(Alias _ _ d, _) -> comp g (App d a')
|
||||||
|
|
||||||
|
(S (T i cs) e,_) -> prawitz g i (flip App a') cs e
|
||||||
|
|
||||||
|
_ -> returnC $ appPredefined $ App f' a'
|
||||||
|
P t l -> do
|
||||||
|
t' <- comp g t
|
||||||
|
case t' of
|
||||||
|
FV rs -> mapM (\c -> comp g (P c l)) rs >>= returnC . FV
|
||||||
|
R r -> maybe (prtBad "no value for label" l) (comp g . snd) $ lookup l r
|
||||||
|
|
||||||
|
ExtR (R a) b -> -- NOT POSSIBLE both a and b records!
|
||||||
|
case comp g (P (R a) l) of
|
||||||
|
Ok v -> return v
|
||||||
|
_ -> comp g (P b l)
|
||||||
|
ExtR a (R b) ->
|
||||||
|
case comp g (P (R b) l) of
|
||||||
|
Ok v -> return v
|
||||||
|
_ -> comp g (P a l)
|
||||||
|
|
||||||
|
Alias _ _ r -> comp g (P r l)
|
||||||
|
|
||||||
|
S (T i cs) e -> prawitz g i (flip P l) cs e
|
||||||
|
|
||||||
|
_ -> returnC $ P t' l
|
||||||
|
|
||||||
|
S t v -> do
|
||||||
|
t' <- comp g t
|
||||||
|
v' <- comp g v
|
||||||
|
case t' of
|
||||||
|
T _ [(PV IW,c)] -> comp g c --- an optimization
|
||||||
|
T _ [(PT _ (PV IW),c)] -> comp g c
|
||||||
|
|
||||||
|
T _ [(PV z,c)] -> comp (ext z v' g) c --- another optimization
|
||||||
|
T _ [(PT _ (PV z),c)] -> comp (ext z v' g) c
|
||||||
|
|
||||||
|
FV ccs -> mapM (\c -> comp g (S c v')) ccs >>= returnC . FV
|
||||||
|
|
||||||
|
T _ cc -> case v' of
|
||||||
|
FV vs -> mapM (\c -> comp g (S t' c)) vs >>= returnC . FV
|
||||||
|
_ -> case matchPattern cc v' of
|
||||||
|
Ok (c,g') -> comp (g' ++ g) c
|
||||||
|
_ | isCan v' -> prtBad ("missing case" +++ prt v' +++ "in") t
|
||||||
|
_ -> return $ S t' v' -- if v' is not canonical
|
||||||
|
|
||||||
|
Alias _ _ d -> comp g (S d v')
|
||||||
|
|
||||||
|
S (T i cs) e -> prawitz g i (flip S v') cs e
|
||||||
|
|
||||||
|
_ -> returnC $ S t' v'
|
||||||
|
|
||||||
|
-- glue if you can
|
||||||
|
Glue x0 y0 -> do
|
||||||
|
x <- comp g x0
|
||||||
|
y <- comp g y0
|
||||||
|
case (x,y) of
|
||||||
|
(Alias _ _ d, y) -> comp g $ Glue d y
|
||||||
|
(x, Alias _ _ d) -> comp g $ Glue x d
|
||||||
|
|
||||||
|
(S (T i cs) e, s) -> prawitz g i (flip Glue s) cs e
|
||||||
|
(s, S (T i cs) e) -> prawitz g i (Glue s) cs e
|
||||||
|
(_,K "") -> return x
|
||||||
|
(K "",_) -> return y
|
||||||
|
(K a, K b) -> return $ K (a ++ b)
|
||||||
|
(K a, Alts (d,vs)) -> do
|
||||||
|
let glx = Glue x
|
||||||
|
comp g $ Alts (glx d, [(glx v,c) | (v,c) <- vs])
|
||||||
|
(Alts _, K a) -> do
|
||||||
|
x' <- strsFromTerm x
|
||||||
|
return $ variants [
|
||||||
|
foldr1 C (map K (str2strings (glueStr v (str a)))) | v <- x']
|
||||||
|
_ -> do
|
||||||
|
mapM_ checkNoArgVars [x,y]
|
||||||
|
r <- composOp (comp g) t
|
||||||
|
returnC r
|
||||||
|
|
||||||
|
Alts _ -> do
|
||||||
|
r <- composOp (comp g) t
|
||||||
|
returnC r
|
||||||
|
|
||||||
|
-- remove empty
|
||||||
|
C a b -> do
|
||||||
|
a' <- comp g a
|
||||||
|
b' <- comp g b
|
||||||
|
returnC $ case (a',b') of
|
||||||
|
(Empty,_) -> b'
|
||||||
|
(_,Empty) -> a'
|
||||||
|
_ -> C a' b'
|
||||||
|
|
||||||
|
-- reduce free variation as much as you can
|
||||||
|
FV [t] -> comp g t
|
||||||
|
|
||||||
|
-- merge record extensions if you can
|
||||||
|
ExtR r s -> do
|
||||||
|
r' <- comp g r
|
||||||
|
s' <- comp g s
|
||||||
|
case (r',s') of
|
||||||
|
(Alias _ _ d, _) -> comp g $ ExtR d s'
|
||||||
|
(_, Alias _ _ d) -> comp g $ Glue r' d
|
||||||
|
|
||||||
|
(R rs, R ss) -> return $ R (rs ++ ss)
|
||||||
|
(RecType rs, RecType ss) -> return $ RecType (rs ++ ss)
|
||||||
|
_ -> return $ ExtR r' s'
|
||||||
|
|
||||||
|
-- case-expand tables
|
||||||
|
T i cs -> do
|
||||||
|
pty0 <- getTableType i
|
||||||
|
ptyp <- comp g pty0
|
||||||
|
case allParamValues gr ptyp of
|
||||||
|
Ok vs -> do
|
||||||
|
|
||||||
|
cs' <- mapM (compBranchOpt g) cs
|
||||||
|
sts <- mapM (matchPattern cs') vs
|
||||||
|
ts <- mapM (\ (c,g') -> comp (g' ++ g) c) sts
|
||||||
|
ps <- mapM term2patt vs
|
||||||
|
let ps' = ps --- PT ptyp (head ps) : tail ps
|
||||||
|
return $ T (TComp ptyp) (zip ps' ts)
|
||||||
|
_ -> do
|
||||||
|
cs' <- mapM (compBranch g) cs
|
||||||
|
return $ T i cs' -- happens with variable types
|
||||||
|
|
||||||
|
Alias c a d -> do
|
||||||
|
d' <- comp g d
|
||||||
|
return $ Alias c a d' -- alias only disappears in certain redexes
|
||||||
|
|
||||||
|
-- otherwise go ahead
|
||||||
|
_ -> composOp (comp g) t >>= returnC
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
look = lookupResDef gr
|
||||||
|
|
||||||
|
ext x a g = (x,a):g
|
||||||
|
|
||||||
|
returnC = return --- . computed
|
||||||
|
|
||||||
|
variants [t] = t
|
||||||
|
variants ts = FV ts
|
||||||
|
|
||||||
|
isCan v = case v of
|
||||||
|
Con _ -> True
|
||||||
|
QC _ _ -> True
|
||||||
|
App f a -> isCan f && isCan a
|
||||||
|
R rs -> all (isCan . snd . snd) rs
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
compBranch g (p,v) = do
|
||||||
|
let g' = contP p ++ g
|
||||||
|
v' <- comp g' v
|
||||||
|
return (p,v')
|
||||||
|
|
||||||
|
compBranchOpt g c@(p,v) = case contP p of
|
||||||
|
[] -> return c
|
||||||
|
_ -> err (const (return c)) return $ compBranch g c
|
||||||
|
|
||||||
|
contP p = case p of
|
||||||
|
PV x -> [(x,Vr x)]
|
||||||
|
PC _ ps -> concatMap contP ps
|
||||||
|
PP _ _ ps -> concatMap contP ps
|
||||||
|
PT _ p -> contP p
|
||||||
|
PR rs -> concatMap (contP . snd) rs
|
||||||
|
_ -> []
|
||||||
|
|
||||||
|
prawitz g i f cs e = do
|
||||||
|
cs' <- mapM (compBranch g) [(p, f v) | (p,v) <- cs]
|
||||||
|
return $ S (T i cs') e
|
||||||
|
|
||||||
|
-- argument variables cannot be glued
|
||||||
|
|
||||||
|
checkNoArgVars :: Term -> Err Term
|
||||||
|
checkNoArgVars t = case t of
|
||||||
|
Vr (IA _) -> prtBad "cannot glue (+) term with run-time variable" t
|
||||||
|
Vr (IAV _) -> prtBad "cannot glue (+) term with run-time variable" t
|
||||||
|
_ -> composOp checkNoArgVars t
|
||||||
154
src/GF/Grammar/Grammar.hs
Normal file
154
src/GF/Grammar/Grammar.hs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
module Grammar where
|
||||||
|
|
||||||
|
import Str
|
||||||
|
import Ident
|
||||||
|
import Option ---
|
||||||
|
import Modules
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
|
||||||
|
-- AR 23/1/2000 -- 30/5/2001 -- 4/5/2003
|
||||||
|
|
||||||
|
-- grammar as presented to the compiler
|
||||||
|
|
||||||
|
type SourceGrammar = MGrammar Ident Option Info
|
||||||
|
|
||||||
|
type SourceModInfo = ModInfo Ident Option Info
|
||||||
|
|
||||||
|
type SourceModule = (Ident, SourceModInfo)
|
||||||
|
|
||||||
|
type SourceAbs = Module Ident Option Info
|
||||||
|
type SourceRes = Module Ident Option Info
|
||||||
|
type SourceCnc = Module Ident Option Info
|
||||||
|
|
||||||
|
-- judgements in abstract syntax
|
||||||
|
|
||||||
|
data Info =
|
||||||
|
AbsCat (Perh Context) (Perh [Fun]) -- constructors
|
||||||
|
| AbsFun (Perh Type) (Perh Term) -- Yes f = canonical
|
||||||
|
| AbsTrans Ident
|
||||||
|
|
||||||
|
-- judgements in resource
|
||||||
|
| ResParam (Perh [Param])
|
||||||
|
| ResValue (Perh Type) -- to mark parameter constructors for lookup
|
||||||
|
| ResOper (Perh Type) (Perh Term)
|
||||||
|
|
||||||
|
-- judgements in concrete syntax
|
||||||
|
| CncCat (Perh Type) (Perh Term) MPr -- lindef ini'zed,
|
||||||
|
| CncFun (Maybe (Ident,(Context,Type))) (Perh Term) MPr -- type info added at TC
|
||||||
|
|
||||||
|
-- indirection to module Ident; the Bool says if canonical
|
||||||
|
| AnyInd Bool Ident
|
||||||
|
deriving (Read, Show)
|
||||||
|
|
||||||
|
type Perh a = Perhaps a Ident -- to express indirection to other module
|
||||||
|
|
||||||
|
type MPr = Perhaps Term Ident -- printname
|
||||||
|
|
||||||
|
type Type = Term
|
||||||
|
type Cat = QIdent
|
||||||
|
type Fun = QIdent
|
||||||
|
|
||||||
|
type QIdent = (Ident,Ident)
|
||||||
|
|
||||||
|
data Term =
|
||||||
|
Vr Ident -- variable
|
||||||
|
| Cn Ident -- constant
|
||||||
|
| Con Ident -- constructor
|
||||||
|
| Sort String -- basic type
|
||||||
|
| EInt Int -- integer literal
|
||||||
|
| K String -- string literal or token: "foo"
|
||||||
|
| Empty -- the empty string []
|
||||||
|
|
||||||
|
| App Term Term -- application: f a
|
||||||
|
| Abs Ident Term -- abstraction: \x -> b
|
||||||
|
| Meta MetaSymb -- metavariable: ?i (only parsable: ? = ?0)
|
||||||
|
| Prod Ident Term Term -- function type: (x : A) -> B
|
||||||
|
| Eqs [Equation] -- abstraction by cases: fn {x y -> b ; z u -> c}
|
||||||
|
-- only used in internal representation
|
||||||
|
| Typed Term Term -- type-annotated term
|
||||||
|
|
||||||
|
| ECase Term [Branch] -- case expression in abstract syntax à la Alfa
|
||||||
|
|
||||||
|
-- below this only for concrete syntax
|
||||||
|
| RecType [Labelling] -- record type: { p : A ; ...}
|
||||||
|
| R [Assign] -- record: { p = a ; ...}
|
||||||
|
| P Term Label -- projection: r.p
|
||||||
|
| ExtR Term Term -- extension: R ** {x : A} (both types and terms)
|
||||||
|
|
||||||
|
| Table Term Term -- table type: P => A
|
||||||
|
| T TInfo [Case] -- table: table {p => c ; ...}
|
||||||
|
| S Term Term -- selection: t ! p
|
||||||
|
|
||||||
|
| Let LocalDef Term -- local definition: let {t : T = a} in b
|
||||||
|
|
||||||
|
| Alias Ident Type Term -- constant and its definition, used in inlining
|
||||||
|
|
||||||
|
| Q Ident Ident -- qualified constant from a package
|
||||||
|
| QC Ident Ident -- qualified constructor from a package
|
||||||
|
|
||||||
|
| C Term Term -- concatenation: s ++ t
|
||||||
|
| Glue Term Term -- agglutination: s + t
|
||||||
|
|
||||||
|
| FV [Term] -- alternatives in free variation: variants { s ; ... }
|
||||||
|
|
||||||
|
| Alts (Term, [(Term, Term)]) -- alternatives by prefix: pre {t ; s/c ; ...}
|
||||||
|
| Strs [Term] -- conditioning prefix strings: strs {s ; ...}
|
||||||
|
|
||||||
|
--- these three are obsolete
|
||||||
|
| LiT Ident -- linearization type
|
||||||
|
| Ready Str -- result of compiling; not to be parsed ...
|
||||||
|
| Computed Term -- result of computing: not to be reopened nor parsed
|
||||||
|
|
||||||
|
deriving (Read, Show, Eq, Ord)
|
||||||
|
|
||||||
|
data Patt =
|
||||||
|
PC Ident [Patt] -- constructor pattern: C p1 ... pn C
|
||||||
|
| PP Ident Ident [Patt] -- package constructor pattern: P.C p1 ... pn P.C
|
||||||
|
| PV Ident -- variable pattern: x
|
||||||
|
| PW -- wild card pattern: _
|
||||||
|
| PR [(Label,Patt)] -- record pattern: {r = p ; ...} -- only concrete
|
||||||
|
| PString String -- string literal pattern: "foo" -- only abstract
|
||||||
|
| PInt Int -- integer literal pattern: 12 -- only abstract
|
||||||
|
| PT Type Patt -- type-annotated pattern
|
||||||
|
deriving (Read, Show, Eq, Ord)
|
||||||
|
|
||||||
|
-- to guide computation and type checking of tables
|
||||||
|
data TInfo =
|
||||||
|
TRaw -- received from parser; can be anything
|
||||||
|
| TTyped Type -- type annontated, but can be anything
|
||||||
|
| TComp Type -- expanded
|
||||||
|
| TWild Type -- just one wild card pattern, no need to expand
|
||||||
|
deriving (Read, Show, Eq, Ord)
|
||||||
|
|
||||||
|
data Label =
|
||||||
|
LIdent String
|
||||||
|
| LVar Int
|
||||||
|
deriving (Read, Show, Eq, Ord) -- record label
|
||||||
|
|
||||||
|
newtype MetaSymb = MetaSymb Int deriving (Read, Show, Eq, Ord)
|
||||||
|
|
||||||
|
type Decl = (Ident,Term) -- (x:A) (_:A) A
|
||||||
|
type Context = [Decl] -- (x:A)(y:B) (x,y:A) (_,_:A)
|
||||||
|
type Equation = ([Patt],Term)
|
||||||
|
|
||||||
|
type Labelling = (Label, Term)
|
||||||
|
type Assign = (Label, (Maybe Type, Term))
|
||||||
|
type Case = (Patt, Term)
|
||||||
|
type LocalDef = (Ident, (Maybe Type, Term))
|
||||||
|
|
||||||
|
type Param = (Ident, Context)
|
||||||
|
type Altern = (Term, [(Term, Term)])
|
||||||
|
|
||||||
|
type Substitution = [(Ident, Term)]
|
||||||
|
|
||||||
|
-- branches à la Alfa
|
||||||
|
newtype Branch = Branch (Con,([Ident],Term)) deriving (Eq, Ord,Show,Read)
|
||||||
|
type Con = Ident ---
|
||||||
|
|
||||||
|
varLabel = LVar
|
||||||
|
|
||||||
|
wildPatt :: Patt
|
||||||
|
wildPatt = PV wildIdent
|
||||||
|
|
||||||
|
type Trm = Term
|
||||||
125
src/GF/Grammar/LookAbs.hs
Normal file
125
src/GF/Grammar/LookAbs.hs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
module LookAbs where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import qualified GFC as C
|
||||||
|
import Abstract
|
||||||
|
import Ident
|
||||||
|
|
||||||
|
import Modules
|
||||||
|
|
||||||
|
import List (nub)
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
type GFCGrammar = C.CanonGrammar
|
||||||
|
|
||||||
|
lookupAbsDef :: GFCGrammar -> Ident -> Ident -> Err (Maybe Term)
|
||||||
|
lookupAbsDef gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
C.AbsFun _ t -> return $ return t
|
||||||
|
C.AnyInd _ n -> lookupAbsDef gr n c
|
||||||
|
_ -> return Nothing
|
||||||
|
_ -> Bad $ prt m +++ "is not an abstract module"
|
||||||
|
|
||||||
|
lookupFunType :: GFCGrammar -> Ident -> Ident -> Err Type
|
||||||
|
lookupFunType gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
C.AbsFun t _ -> return t
|
||||||
|
C.AnyInd _ n -> lookupFunType gr n c
|
||||||
|
_ -> prtBad "cannot find type of" c
|
||||||
|
_ -> Bad $ prt m +++ "is not an abstract module"
|
||||||
|
|
||||||
|
lookupCatContext :: GFCGrammar -> Ident -> Ident -> Err Context
|
||||||
|
lookupCatContext gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
C.AbsCat co _ -> return co
|
||||||
|
C.AnyInd _ n -> lookupCatContext gr n c
|
||||||
|
_ -> prtBad "unknown category" c
|
||||||
|
_ -> Bad $ prt m +++ "is not an abstract module"
|
||||||
|
|
||||||
|
---- should be revised (20/9/2003)
|
||||||
|
isPrimitiveFun :: GFCGrammar -> Fun -> Bool
|
||||||
|
isPrimitiveFun gr (m,c) = case lookupAbsDef gr m c of
|
||||||
|
Ok (Just (Eqs [])) -> True -- is canonical
|
||||||
|
Ok (Just _) -> False -- has defining clauses
|
||||||
|
_ -> True -- has no definition
|
||||||
|
|
||||||
|
|
||||||
|
-- looking up refinement terms
|
||||||
|
|
||||||
|
lookupRef :: GFCGrammar -> Binds -> Term -> Err Val
|
||||||
|
lookupRef gr binds at = case at of
|
||||||
|
Q m f -> lookupFunType gr m f >>= return . vClos
|
||||||
|
Vr i -> maybeErr ("unknown variable" +++ prt at) $ lookup i binds
|
||||||
|
_ -> prtBad "cannot refine with complex term" at ---
|
||||||
|
|
||||||
|
refsForType :: (Val -> Type -> Bool) -> GFCGrammar -> Binds -> Val -> [(Term,Val)]
|
||||||
|
refsForType compat gr binds val =
|
||||||
|
[(vr i, t) | (i,t) <- binds, Ok ty <- [val2exp t], compat val ty] ++
|
||||||
|
[(qq f, vClos t) | (f,t) <- funsForType compat gr val]
|
||||||
|
|
||||||
|
|
||||||
|
funRulesOf :: GFCGrammar -> [(Fun,Type)]
|
||||||
|
funRulesOf gr =
|
||||||
|
---- funRulesForLiterals ++
|
||||||
|
[((i,f),typ) | (i, ModMod m) <- modules gr,
|
||||||
|
mtype m == MTAbstract,
|
||||||
|
(f, C.AbsFun typ _) <- tree2list (jments m)]
|
||||||
|
|
||||||
|
allCatsOf :: GFCGrammar -> [(Cat,Context)]
|
||||||
|
allCatsOf gr =
|
||||||
|
[((i,c),cont) | (i, ModMod m) <- modules gr,
|
||||||
|
isModAbs m,
|
||||||
|
(c, C.AbsCat cont _) <- tree2list (jments m)]
|
||||||
|
|
||||||
|
funsForType :: (Val -> Type -> Bool) -> GFCGrammar -> Val -> [(Fun,Type)]
|
||||||
|
funsForType compat gr val = [(fun,typ) | (fun,typ) <- funRulesOf gr,
|
||||||
|
compat val typ]
|
||||||
|
|
||||||
|
funsOnType :: (Val -> Type -> Bool) -> GFCGrammar -> Val -> [((Fun,Int),Type)]
|
||||||
|
funsOnType compat gr = funsOnTypeFs compat (funRulesOf gr)
|
||||||
|
|
||||||
|
funsOnTypeFs :: (Val -> Type -> Bool) -> [(Fun,Type)] -> Val -> [((Fun,Int),Type)]
|
||||||
|
funsOnTypeFs compat fs val = [((fun,i),typ) |
|
||||||
|
(fun,typ) <- fs,
|
||||||
|
Ok (args,_,_) <- [typeForm typ],
|
||||||
|
(i,arg) <- zip [0..] (map snd args),
|
||||||
|
compat val arg]
|
||||||
|
|
||||||
|
|
||||||
|
-- this is needed at compile time
|
||||||
|
|
||||||
|
lookupFunTypeSrc :: Grammar -> Ident -> Ident -> Err Type
|
||||||
|
lookupFunTypeSrc gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
AbsFun (Yes t) _ -> return t
|
||||||
|
AnyInd _ n -> lookupFunTypeSrc gr n c
|
||||||
|
_ -> prtBad "cannot find type of" c
|
||||||
|
_ -> Bad $ prt m +++ "is not an abstract module"
|
||||||
|
|
||||||
|
lookupCatContextSrc :: Grammar -> Ident -> Ident -> Err Context
|
||||||
|
lookupCatContextSrc gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
AbsCat (Yes co) _ -> return co
|
||||||
|
AnyInd _ n -> lookupCatContextSrc gr n c
|
||||||
|
_ -> prtBad "unknown category" c
|
||||||
|
_ -> Bad $ prt m +++ "is not an abstract module"
|
||||||
393
src/GF/Grammar/Lookup.hs
Normal file
393
src/GF/Grammar/Lookup.hs
Normal file
@@ -0,0 +1,393 @@
|
|||||||
|
module Lookup where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Abstract
|
||||||
|
import Modules
|
||||||
|
|
||||||
|
import List (nub)
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- lookup in resource and concrete in compiling; for abstract, use Look
|
||||||
|
|
||||||
|
lookupResDef :: SourceGrammar -> Ident -> Ident -> Err Term
|
||||||
|
lookupResDef gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
ResOper _ (Yes t) -> return $ qualifAnnot m t
|
||||||
|
AnyInd _ n -> lookupResDef gr n c
|
||||||
|
ResParam _ -> return $ QC m c
|
||||||
|
ResValue _ -> return $ QC m c
|
||||||
|
_ -> Bad $ prt c +++ "is not defined in resource" +++ prt m
|
||||||
|
_ -> Bad $ prt m +++ "is not a resource"
|
||||||
|
|
||||||
|
lookupResType :: SourceGrammar -> Ident -> Ident -> Err Type
|
||||||
|
lookupResType gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
ResOper (Yes t) _ -> return $ qualifAnnot m t
|
||||||
|
AnyInd _ n -> lookupResType gr n c
|
||||||
|
ResParam _ -> return $ typePType
|
||||||
|
ResValue (Yes t) -> return $ qualifAnnotPar m t
|
||||||
|
_ -> Bad $ prt c +++ "has no type defined in resource" +++ prt m
|
||||||
|
_ -> Bad $ prt m +++ "is not a resource"
|
||||||
|
|
||||||
|
lookupParams :: SourceGrammar -> Ident -> Ident -> Err [Param]
|
||||||
|
lookupParams gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
ResParam (Yes ps) -> return ps
|
||||||
|
AnyInd _ n -> lookupParams gr n c
|
||||||
|
_ -> Bad $ prt c +++ "has no parameters defined in resource" +++ prt m
|
||||||
|
_ -> Bad $ prt m +++ "is not a resource"
|
||||||
|
|
||||||
|
lookupParamValues :: SourceGrammar -> Ident -> Ident -> Err [Term]
|
||||||
|
lookupParamValues gr m c = do
|
||||||
|
ps <- lookupParams gr m c
|
||||||
|
liftM concat $ mapM mkPar ps
|
||||||
|
where
|
||||||
|
mkPar (f,co) = do
|
||||||
|
vs <- liftM combinations $ mapM (\ (_,ty) -> allParamValues gr ty) co
|
||||||
|
return $ map (mkApp (QC m f)) vs
|
||||||
|
|
||||||
|
lookupFirstTag :: SourceGrammar -> Ident -> Ident -> Err Term
|
||||||
|
lookupFirstTag gr m c = do
|
||||||
|
vs <- lookupParamValues gr m c
|
||||||
|
case vs of
|
||||||
|
v:_ -> return v
|
||||||
|
_ -> prtBad "no parameter values given to type" c
|
||||||
|
|
||||||
|
allParamValues :: SourceGrammar -> Type -> Err [Term]
|
||||||
|
allParamValues cnc ptyp = case ptyp of
|
||||||
|
QC p c -> lookupParamValues cnc p c
|
||||||
|
RecType r -> do
|
||||||
|
let (ls,tys) = unzip r
|
||||||
|
tss <- mapM allPV tys
|
||||||
|
return [R (zipAssign ls ts) | ts <- combinations tss]
|
||||||
|
_ -> prtBad "cannot find parameter values for" ptyp
|
||||||
|
where
|
||||||
|
allPV = allParamValues cnc
|
||||||
|
|
||||||
|
qualifAnnot :: Ident -> Term -> Term
|
||||||
|
qualifAnnot _ = id
|
||||||
|
-- Using this we wouldn't have to annotate constants defined in a module itself.
|
||||||
|
-- But things are simpler if we do (cf. Zinc).
|
||||||
|
-- Change Rename.self2status to change this behaviour.
|
||||||
|
|
||||||
|
-- we need this for lookup in ResVal
|
||||||
|
qualifAnnotPar m t = case t of
|
||||||
|
Cn c -> Q m c
|
||||||
|
Con c -> QC m c
|
||||||
|
_ -> composSafeOp (qualifAnnotPar m) t
|
||||||
|
|
||||||
|
|
||||||
|
lookupLincat :: SourceGrammar -> Ident -> Ident -> Err Type
|
||||||
|
lookupLincat gr m c = do
|
||||||
|
mi <- lookupModule gr m
|
||||||
|
case mi of
|
||||||
|
ModMod mo -> do
|
||||||
|
info <- lookupInfo mo c
|
||||||
|
case info of
|
||||||
|
CncCat (Yes t) _ _ -> return t
|
||||||
|
AnyInd _ n -> lookupLincat gr n c
|
||||||
|
_ -> Bad $ prt c +++ "has no linearization type in" +++ prt m
|
||||||
|
_ -> Bad $ prt m +++ "is not concrete"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{-
|
||||||
|
-- the type of oper may have to be inferred at TC, so it may be junk before it
|
||||||
|
|
||||||
|
lookupResIdent :: Ident -> [(Ident, SourceRes)] -> Err (Term,Type)
|
||||||
|
lookupResIdent c ms = case lookupWhich ms c of
|
||||||
|
Ok (i,info) -> case info of
|
||||||
|
ResOper (Yes t) _ -> return (Q i c, t)
|
||||||
|
ResOper _ _ -> return (Q i c, undefined) ----
|
||||||
|
ResParam _ -> return (Q i c, typePType)
|
||||||
|
ResValue (Yes t) -> return (QC i c, t)
|
||||||
|
_ -> Bad $ "not found in resource" +++ prt c
|
||||||
|
|
||||||
|
-- NB we only have to look up cnc in canonical!
|
||||||
|
|
||||||
|
-- you may want to strip the qualification if the module is the current one
|
||||||
|
|
||||||
|
stripMod :: Ident -> Term -> Term
|
||||||
|
stripMod m t = case t of
|
||||||
|
Q n c | n==m -> Cn c
|
||||||
|
QC n c | n==m -> Con c
|
||||||
|
_ -> t
|
||||||
|
|
||||||
|
-- what you want may be a pattern and not a term. Then use Macros.term2patt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- an auxiliary for making ordered search through a list of modules
|
||||||
|
|
||||||
|
lookups :: Ord i => (i -> m -> Err (Perhaps a m)) -> i -> [m] -> Err (Perhaps a m)
|
||||||
|
lookups look c [] = Bad "not found in any module"
|
||||||
|
lookups look c (m:ms) = case look c m of
|
||||||
|
Ok (Yes v) -> return $ Yes v
|
||||||
|
Ok (May m') -> look c m'
|
||||||
|
_ -> lookups look c ms
|
||||||
|
|
||||||
|
|
||||||
|
lookupAbstract :: AbstractST -> Ident -> Err AbsInfo
|
||||||
|
lookupAbstract g i = errIn ("not found in abstract" +++ prt i) $ lookupTree prt i g
|
||||||
|
|
||||||
|
lookupFunsToCat :: AbstractST -> Ident -> Err [Fun]
|
||||||
|
lookupFunsToCat g c = errIn ("looking up functions to category" +++ prt c) $ do
|
||||||
|
info <- lookupAbstract g c
|
||||||
|
case info of
|
||||||
|
AbsCat _ _ fs _ -> return fs
|
||||||
|
_ -> prtBad "not category" c
|
||||||
|
|
||||||
|
allFunsWithValCat ab = [(f,c) | (c, AbsCat _ _ fs _) <- abstr2list ab, f <- fs]
|
||||||
|
|
||||||
|
allDefs ab = [(f,d) | (f,AbsFun _ (Just d)) <- abstr2list ab]
|
||||||
|
|
||||||
|
lookupCatContext :: AbstractST -> Ident -> Err Context
|
||||||
|
lookupCatContext g c = errIn "context of category" $ do
|
||||||
|
info <- lookupAbstract g c
|
||||||
|
case info of
|
||||||
|
AbsCat c _ _ _ -> return c
|
||||||
|
_ -> prtBad "not category" c
|
||||||
|
|
||||||
|
lookupFunType :: AbstractST -> Ident -> Err Term
|
||||||
|
lookupFunType g c = errIn "looking up type of function" $ case c of
|
||||||
|
IL s -> lookupLiteral s >>= return . fst
|
||||||
|
_ -> do
|
||||||
|
info <- lookupAbstract g c
|
||||||
|
case info of
|
||||||
|
AbsFun t _ -> return t
|
||||||
|
AbsType t -> return typeType
|
||||||
|
_ -> prtBad "not function" c
|
||||||
|
|
||||||
|
lookupFunArity :: AbstractST -> Ident -> Err Int
|
||||||
|
lookupFunArity g c = do
|
||||||
|
typ <- lookupFunType g c
|
||||||
|
ctx <- contextOfType typ
|
||||||
|
return $ length ctx
|
||||||
|
|
||||||
|
lookupAbsDef :: AbstractST -> Ident -> Err (Maybe Term)
|
||||||
|
lookupAbsDef g c = errIn "looking up definition in abstract syntax" $ do
|
||||||
|
info <- lookupAbstract g c
|
||||||
|
case info of
|
||||||
|
AbsFun _ t -> return t
|
||||||
|
AbsType t -> return $ Just t
|
||||||
|
_ -> return $ Nothing -- constant found and accepted as primitive
|
||||||
|
|
||||||
|
|
||||||
|
allCats :: AbstractST -> [Ident]
|
||||||
|
allCats abstr = [c | (c, AbsCat _ _ _ _) <- abstr2list abstr]
|
||||||
|
|
||||||
|
allIndepCats :: AbstractST -> [Ident]
|
||||||
|
allIndepCats abstr = [c | (c, AbsCat [] _ _ _) <- abstr2list abstr]
|
||||||
|
|
||||||
|
lookupConcrete :: ConcreteST -> Ident -> Err CncInfo
|
||||||
|
lookupConcrete g i = errIn ("not found in concrete" +++ prt i) $ lookupTree prt i g
|
||||||
|
|
||||||
|
lookupPackage :: ConcreteST -> Ident -> Err ([Ident], ConcreteST)
|
||||||
|
lookupPackage g p = do
|
||||||
|
info <- lookupConcrete g p
|
||||||
|
case info of
|
||||||
|
CncPackage ps ins -> return (ps,ins)
|
||||||
|
_ -> prtBad "not package" p
|
||||||
|
|
||||||
|
lookupInPackage :: ConcreteST -> (Ident,Ident) -> Err CncInfo
|
||||||
|
lookupInPackage = lookupLift (flip (lookupTree prt))
|
||||||
|
|
||||||
|
lookupInAll :: [BinTree (Ident,b)] -> Ident -> Err b
|
||||||
|
lookupInAll = lookInAll (flip (lookupTree prt))
|
||||||
|
|
||||||
|
lookInAll :: (BinTree (Ident,c) -> Ident -> Err b) ->
|
||||||
|
[BinTree (Ident,c)] -> Ident -> Err b
|
||||||
|
lookInAll look ts c = case ts of
|
||||||
|
t : ts' -> err (const $ lookInAll look ts' c) return $ look t c
|
||||||
|
[] -> prtBad "not found in any package" c
|
||||||
|
|
||||||
|
lookupLift :: (ConcreteST -> Ident -> Err b) ->
|
||||||
|
ConcreteST -> (Ident,Ident) -> Err b
|
||||||
|
lookupLift look g (p,f) = do
|
||||||
|
(ps,ins) <- lookupPackage g p
|
||||||
|
ps' <- mapM (lookupPackage g) ps
|
||||||
|
lookInAll look (ins : reverse (map snd ps')) f
|
||||||
|
|
||||||
|
termFromPackage :: ConcreteST -> Ident -> Term -> Err Term
|
||||||
|
termFromPackage g p = termFP where
|
||||||
|
termFP t = case t of
|
||||||
|
Cn c -> return $ if isInPack c
|
||||||
|
then Q p c
|
||||||
|
else Cn c
|
||||||
|
T (TTyped t) cs -> do
|
||||||
|
t' <- termFP t
|
||||||
|
liftM (T (TTyped t')) $ mapM branchInPack cs
|
||||||
|
T i cs -> liftM (T i) $ mapM branchInPack cs
|
||||||
|
_ -> composOp termFP t
|
||||||
|
isInPack c = case lookupInPackage g (p,c) of
|
||||||
|
Ok _ -> True
|
||||||
|
_ -> False
|
||||||
|
branchInPack (q,t) = do
|
||||||
|
p' <- pattInPack q
|
||||||
|
t' <- termFP t
|
||||||
|
return (p',t')
|
||||||
|
pattInPack q = case q of
|
||||||
|
PC c ps -> do
|
||||||
|
let pc = if isInPack c
|
||||||
|
then PP p c
|
||||||
|
else PC c
|
||||||
|
ps' <- mapM pattInPack ps
|
||||||
|
return $ pc ps'
|
||||||
|
_ -> return q
|
||||||
|
|
||||||
|
lookupCncDef :: ConcreteST -> Ident -> Err Term
|
||||||
|
lookupCncDef g t@(IL _) = return $ cn t
|
||||||
|
lookupCncDef g c = errIn "looking up defining term" $ do
|
||||||
|
info <- lookupConcrete g c
|
||||||
|
case info of
|
||||||
|
CncOper _ t _ -> return t -- the definition
|
||||||
|
CncCat t _ _ _ -> return t -- the linearization type
|
||||||
|
_ -> return $ Cn c -- constant found and accepted
|
||||||
|
|
||||||
|
lookupOperDef :: ConcreteST -> Ident -> Err Term
|
||||||
|
lookupOperDef g c = errIn "looking up defining term of oper" $ do
|
||||||
|
info <- lookupConcrete g c
|
||||||
|
case info of
|
||||||
|
CncOper _ t _ -> return t
|
||||||
|
_ -> prtBad "not oper" c
|
||||||
|
|
||||||
|
lookupLincat :: ConcreteST -> Ident -> Err Term
|
||||||
|
lookupLincat g c = return $ errVal defaultLinType $ do
|
||||||
|
info <- lookupConcrete g c
|
||||||
|
case info of
|
||||||
|
CncCat t _ _ _ -> return t
|
||||||
|
_ -> prtBad "not category" c
|
||||||
|
|
||||||
|
lookupLindef :: ConcreteST -> Ident -> Err Term
|
||||||
|
lookupLindef g c = return $ errVal linDefStr $ do
|
||||||
|
info <- lookupConcrete g c
|
||||||
|
case info of
|
||||||
|
CncCat _ (Just t) _ _ -> return t
|
||||||
|
CncCat _ _ _ _ -> return $ linDefStr --- wrong: this is only sof {s:Str}
|
||||||
|
_ -> prtBad "not category" c
|
||||||
|
|
||||||
|
lookupLinType :: ConcreteST -> Ident -> Err Type
|
||||||
|
lookupLinType g c = errIn "looking up type in concrete syntax" $ do
|
||||||
|
info <- lookupConcrete g c
|
||||||
|
case info of
|
||||||
|
CncParType _ _ _ -> return typeType
|
||||||
|
CncParam ty _ -> return ty
|
||||||
|
CncOper (Just ty) _ _ -> return ty
|
||||||
|
_ -> prtBad "no type found for" c
|
||||||
|
|
||||||
|
lookupLin :: ConcreteST -> Ident -> Err Term
|
||||||
|
lookupLin g c = errIn "looking up linearization rule" $ do
|
||||||
|
info <- lookupConcrete g c
|
||||||
|
case info of
|
||||||
|
CncFun t _ -> return t
|
||||||
|
_ -> prtBad "not category" c
|
||||||
|
|
||||||
|
lookupFirstTag :: ConcreteST -> Ident -> Err Term
|
||||||
|
lookupFirstTag g c = do
|
||||||
|
vs <- lookupParamValues g c
|
||||||
|
case vs of
|
||||||
|
v:_ -> return v
|
||||||
|
_ -> prtBad "empty parameter type" c
|
||||||
|
|
||||||
|
lookupPrintname :: ConcreteST -> Ident -> Err String
|
||||||
|
lookupPrintname g c = case lookupConcrete g c of
|
||||||
|
Ok info -> case info of
|
||||||
|
CncCat _ _ _ m -> mpr m
|
||||||
|
CncFun _ m -> mpr m
|
||||||
|
CncParType _ _ m -> mpr m
|
||||||
|
CncOper _ _ m -> mpr m
|
||||||
|
_ -> Bad "no possible printname"
|
||||||
|
Bad s -> Bad s
|
||||||
|
where
|
||||||
|
mpr = maybe (Bad "no printname") (return . stringFromTerm)
|
||||||
|
|
||||||
|
-- this variant succeeds even if there's only abstr syntax
|
||||||
|
lookupPrintname' g c = case lookupConcrete g c of
|
||||||
|
Bad _ -> return $ prt c
|
||||||
|
Ok info -> case info of
|
||||||
|
CncCat _ _ _ m -> mpr m
|
||||||
|
CncFun _ m -> mpr m
|
||||||
|
CncParType _ _ m -> mpr m
|
||||||
|
CncOper _ _ m -> mpr m
|
||||||
|
_ -> return $ prt c
|
||||||
|
where
|
||||||
|
mpr = return . maybe (prt c) stringFromTerm
|
||||||
|
|
||||||
|
allOperDefs :: ConcreteST -> [(Ident,CncInfo)]
|
||||||
|
allOperDefs cnc = [d | d@(_, CncOper _ _ _) <- concr2list cnc]
|
||||||
|
|
||||||
|
allPackageDefs :: ConcreteST -> [(Ident,CncInfo)]
|
||||||
|
allPackageDefs cnc = [d | d@(_, CncPackage _ _) <- concr2list cnc]
|
||||||
|
|
||||||
|
allOperDependencies :: ConcreteST -> [(Ident,[Ident])]
|
||||||
|
allOperDependencies cnc =
|
||||||
|
[(f, filter (/= f) $ -- package name may occur in the package itself
|
||||||
|
nub (concatMap (opersInCncInfo cnc f . snd) (tree2list ds))) |
|
||||||
|
(f, CncPackage _ ds) <- allPackageDefs cnc] ++
|
||||||
|
[(f, nub (opersInTerm cnc t)) |
|
||||||
|
(f, CncOper _ t _) <- allOperDefs cnc]
|
||||||
|
|
||||||
|
opersInTerm :: ConcreteST -> Term -> [Ident]
|
||||||
|
opersInTerm cnc t = case t of
|
||||||
|
Cn c -> [c | isOper c]
|
||||||
|
Q p c -> [p]
|
||||||
|
_ -> collectOp ops t
|
||||||
|
where
|
||||||
|
isOper (IL _) = False
|
||||||
|
isOper c = errVal False $ lookupOperDef cnc c >>= return . const True
|
||||||
|
ops = opersInTerm cnc
|
||||||
|
|
||||||
|
-- this is used inside packages, to find references to outside the package
|
||||||
|
opersInCncInfo :: ConcreteST -> Ident -> CncInfo -> [Ident]
|
||||||
|
opersInCncInfo cnc p i = case i of
|
||||||
|
CncOper _ t _-> filter (not . internal) $ opersInTerm cnc t
|
||||||
|
_ -> []
|
||||||
|
where
|
||||||
|
internal c = case lookupInPackage cnc (p,c) of
|
||||||
|
Ok _ -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
opersUsedInLins :: ConcreteST -> [(Ident,[Ident])] -> [Ident]
|
||||||
|
opersUsedInLins cnc deps = do
|
||||||
|
let ops0 = concat [opersInTerm cnc t | (_, CncFun t _) <- concr2list cnc]
|
||||||
|
nub $ closure ops0
|
||||||
|
where
|
||||||
|
closure ops = case [g | (f,fs) <- deps, elem f ops, g <- fs, notElem g ops] of
|
||||||
|
[] -> ops
|
||||||
|
ops' -> ops ++ closure ops'
|
||||||
|
-- presupposes deps are not circular: check this first!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- create refinement and wrapping lists
|
||||||
|
|
||||||
|
|
||||||
|
varOrConst :: AbstractST -> Ident -> Err Term
|
||||||
|
varOrConst abstr c = case lookupFunType abstr c of
|
||||||
|
Ok _ -> return $ Cn c --- bindings cannot overshadow constants
|
||||||
|
_ -> case c of
|
||||||
|
IL _ -> return $ Cn c
|
||||||
|
_ -> return $ Vr c
|
||||||
|
|
||||||
|
-- a rename operation for parsing term input; for abstract syntax and parameters
|
||||||
|
renameTrm :: (Ident -> Err a) -> Term -> Term
|
||||||
|
renameTrm look = ren [] where
|
||||||
|
ren vars t = case t of
|
||||||
|
Vr x | notElem x vars && isNotError (look x) -> Cn x
|
||||||
|
Abs x b -> Abs x $ ren (x:vars) b
|
||||||
|
_ -> composSafeOp (ren vars) t
|
||||||
|
-}
|
||||||
261
src/GF/Grammar/MMacros.hs
Normal file
261
src/GF/Grammar/MMacros.hs
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
module MMacros where
|
||||||
|
|
||||||
|
import Operations
|
||||||
|
import Zipper
|
||||||
|
|
||||||
|
import Grammar
|
||||||
|
import PrGrammar
|
||||||
|
import Ident
|
||||||
|
import Refresh
|
||||||
|
import Values
|
||||||
|
----import GrammarST
|
||||||
|
import Macros
|
||||||
|
|
||||||
|
import Monad
|
||||||
|
|
||||||
|
-- some more abstractions on grammars, esp. for Edit
|
||||||
|
|
||||||
|
nodeTree (Tr (n,_)) = n
|
||||||
|
argsTree (Tr (_,ts)) = ts
|
||||||
|
|
||||||
|
isFocusNode (N (_,_,_,_,b)) = b
|
||||||
|
bindsNode (N (b,_,_,_,_)) = b
|
||||||
|
atomNode (N (_,a,_,_,_)) = a
|
||||||
|
valNode (N (_,_,v,_,_)) = v
|
||||||
|
constrsNode (N (_,_,_,(c,_),_)) = c
|
||||||
|
metaSubstsNode (N (_,_,_,(_,m),_)) = m
|
||||||
|
|
||||||
|
atomTree = atomNode . nodeTree
|
||||||
|
valTree = valNode . nodeTree
|
||||||
|
|
||||||
|
mkNode binds atom vtyp cs = N (binds,atom,vtyp,cs,False)
|
||||||
|
|
||||||
|
type Var = Ident
|
||||||
|
type Meta = MetaSymb
|
||||||
|
|
||||||
|
metasTree :: Tree -> [Meta]
|
||||||
|
metasTree = concatMap metasNode . scanTree where
|
||||||
|
metasNode n = [m | AtM m <- [atomNode n]] ++ map fst (metaSubstsNode n)
|
||||||
|
|
||||||
|
varsTree :: Tree -> [(Var,Val)]
|
||||||
|
varsTree t = [(x,v) | N (_,AtV x,v,_,_) <- scanTree t]
|
||||||
|
|
||||||
|
constrsTree :: Tree -> Constraints
|
||||||
|
constrsTree = constrsNode . nodeTree
|
||||||
|
|
||||||
|
allConstrsTree :: Tree -> Constraints
|
||||||
|
allConstrsTree = concatMap constrsNode . scanTree
|
||||||
|
|
||||||
|
changeConstrs :: (Constraints -> Constraints) -> TrNode -> TrNode
|
||||||
|
changeConstrs f (N (b,a,v,(c,m),x)) = N (b,a,v,(f c, m),x)
|
||||||
|
|
||||||
|
changeMetaSubst :: (MetaSubst -> MetaSubst) -> TrNode -> TrNode
|
||||||
|
changeMetaSubst f (N (b,a,v,(c,m),x)) = N (b,a,v,(c, f m),x)
|
||||||
|
|
||||||
|
changeAtom :: (Atom -> Atom) -> TrNode -> TrNode
|
||||||
|
changeAtom f (N (b,a,v,(c,m),x)) = N (b,f a,v,(c, m),x)
|
||||||
|
|
||||||
|
------ on the way to Edit
|
||||||
|
|
||||||
|
uTree :: Tree
|
||||||
|
uTree = Tr (uNode, []) -- unknown tree
|
||||||
|
|
||||||
|
uNode :: TrNode
|
||||||
|
uNode = mkNode [] uAtom uVal ([],[])
|
||||||
|
|
||||||
|
|
||||||
|
uAtom :: Atom
|
||||||
|
uAtom = AtM meta0
|
||||||
|
|
||||||
|
mAtom :: Atom
|
||||||
|
mAtom = AtM meta0
|
||||||
|
|
||||||
|
uVal :: Val
|
||||||
|
uVal = vClos uExp
|
||||||
|
|
||||||
|
vClos :: Exp -> Val
|
||||||
|
vClos = VClos []
|
||||||
|
|
||||||
|
uExp :: Exp
|
||||||
|
uExp = Meta meta0
|
||||||
|
|
||||||
|
mExp :: Exp
|
||||||
|
mExp = Meta meta0
|
||||||
|
|
||||||
|
mExp0 = mExp
|
||||||
|
|
||||||
|
meta2exp :: MetaSymb -> Exp
|
||||||
|
meta2exp = Meta
|
||||||
|
|
||||||
|
atomC = AtC
|
||||||
|
|
||||||
|
funAtom :: Atom -> Err Fun
|
||||||
|
funAtom a = case a of
|
||||||
|
AtC f -> return f
|
||||||
|
_ -> prtBad "not function head" a
|
||||||
|
|
||||||
|
uBoundVar :: Ident
|
||||||
|
uBoundVar = zIdent "#h" -- used for suppressed bindings
|
||||||
|
|
||||||
|
atomIsMeta :: Atom -> Bool
|
||||||
|
atomIsMeta atom = case atom of
|
||||||
|
AtM _ -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
getMetaAtom a = case a of
|
||||||
|
AtM m -> return m
|
||||||
|
_ -> Bad "the active node is not meta"
|
||||||
|
|
||||||
|
cat2val :: Context -> Cat -> Val
|
||||||
|
cat2val cont cat = vClos $ mkApp (qq cat) [mkMeta i | i <- [1..length cont]]
|
||||||
|
|
||||||
|
val2cat :: Val -> Err Cat
|
||||||
|
val2cat v = val2exp v >>= valCat
|
||||||
|
|
||||||
|
substTerm :: [Ident] -> Substitution -> Term -> Term
|
||||||
|
substTerm ss g c = case c of
|
||||||
|
Vr x -> maybe c id $ lookup x g
|
||||||
|
App f a -> App (substTerm ss g f) (substTerm ss g a)
|
||||||
|
Abs x b -> let y = mkFreshVarX ss x in
|
||||||
|
Abs y (substTerm (y:ss) ((x, Vr y):g) b)
|
||||||
|
Prod x a b -> let y = mkFreshVarX ss x in
|
||||||
|
Prod y (substTerm ss g a) (substTerm (y:ss) ((x,Vr y):g) b)
|
||||||
|
_ -> c
|
||||||
|
|
||||||
|
metaSubstExp :: MetaSubst -> [(Meta,Exp)]
|
||||||
|
metaSubstExp msubst = [(m, errVal (meta2exp m) (val2expSafe v)) | (m,v) <- msubst]
|
||||||
|
|
||||||
|
-- belong here rather than to computation
|
||||||
|
|
||||||
|
substitute :: [Var] -> Substitution -> Exp -> Err Exp
|
||||||
|
substitute v s = return . substTerm v s
|
||||||
|
|
||||||
|
alphaConv :: [Var] -> (Var,Var) -> Exp -> Err Exp ---
|
||||||
|
alphaConv oldvars (x,x') = substitute (x:x':oldvars) [(x,Vr x')]
|
||||||
|
|
||||||
|
alphaFresh :: [Var] -> Exp -> Err Exp
|
||||||
|
alphaFresh vs = refreshTermN $ maxVarIndex vs
|
||||||
|
|
||||||
|
alphaFreshAll :: [Var] -> [Exp] -> Err [Exp]
|
||||||
|
alphaFreshAll vs = mapM $ alphaFresh vs -- done in a state monad
|
||||||
|
|
||||||
|
|
||||||
|
val2exp = val2expP False -- for display
|
||||||
|
val2expSafe = val2expP True -- for type checking
|
||||||
|
|
||||||
|
val2expP :: Bool -> Val -> Err Exp
|
||||||
|
val2expP safe v = case v of
|
||||||
|
|
||||||
|
VClos g@(_:_) e@(Meta _) -> if safe
|
||||||
|
then prtBad "unsafe value substitution" v
|
||||||
|
else substVal g e
|
||||||
|
VClos g e -> substVal g e
|
||||||
|
VApp f c -> liftM2 App (val2expP safe f) (val2expP safe c)
|
||||||
|
VCn c -> return $ qq c
|
||||||
|
VGen i x -> if safe
|
||||||
|
then prtBad "unsafe val2exp" v
|
||||||
|
else return $ vr $ x --- in editing, no alpha conversions presentv
|
||||||
|
where
|
||||||
|
substVal g e = mapPairsM (val2expP safe) g >>= return . (\s -> substTerm [] s e)
|
||||||
|
|
||||||
|
isConstVal :: Val -> Bool
|
||||||
|
isConstVal v = case v of
|
||||||
|
VApp f c -> isConstVal f && isConstVal c
|
||||||
|
VCn _ -> True
|
||||||
|
VClos [] e -> null $ freeVarsExp e
|
||||||
|
_ -> False --- could be more liberal
|
||||||
|
|
||||||
|
mkProdVal :: Binds -> Val -> Err Val ---
|
||||||
|
mkProdVal bs v = do
|
||||||
|
bs' <- mapPairsM val2exp bs
|
||||||
|
v' <- val2exp v
|
||||||
|
return $ vClos $ foldr (uncurry Prod) v' bs'
|
||||||
|
|
||||||
|
freeVarsExp :: Exp -> [Ident]
|
||||||
|
freeVarsExp e = case e of
|
||||||
|
Vr x -> [x]
|
||||||
|
App f c -> freeVarsExp f ++ freeVarsExp c
|
||||||
|
Abs x b -> filter (/=x) (freeVarsExp b)
|
||||||
|
Prod x a b -> freeVarsExp a ++ filter (/=x) (freeVarsExp b)
|
||||||
|
_ -> [] --- thus applies to abstract syntax only
|
||||||
|
|
||||||
|
ident2string = prIdent
|
||||||
|
|
||||||
|
tree :: (TrNode,[Tree]) -> Tree
|
||||||
|
tree = Tr
|
||||||
|
|
||||||
|
eqCat :: Cat -> Cat -> Bool
|
||||||
|
eqCat = (==)
|
||||||
|
|
||||||
|
addBinds :: Binds -> Tree -> Tree
|
||||||
|
addBinds b (Tr (N (b0,at,t,c,x),ts)) = Tr (N (b ++ b0,at,t,c,x),ts)
|
||||||
|
|
||||||
|
bodyTree :: Tree -> Tree
|
||||||
|
bodyTree (Tr (N (_,a,t,c,x),ts)) = Tr (N ([],a,t,c,x),ts)
|
||||||
|
|
||||||
|
refreshMetas :: [Meta] -> Exp -> Exp
|
||||||
|
refreshMetas metas = fst . rms minMeta where
|
||||||
|
rms meta trm = case trm of
|
||||||
|
Meta m -> (Meta meta, nextMeta meta)
|
||||||
|
App f a -> let (f',msf) = rms meta f
|
||||||
|
(a',msa) = rms msf a
|
||||||
|
in (App f' a', msa)
|
||||||
|
Prod x a b ->
|
||||||
|
let (a',msa) = rms meta a
|
||||||
|
(b',msb) = rms msa b
|
||||||
|
in (Prod x a' b', msb)
|
||||||
|
Abs x b -> let (b',msb) = rms meta b in (Abs x b', msb)
|
||||||
|
_ -> (trm,meta)
|
||||||
|
minMeta = int2meta $
|
||||||
|
if null metas then 0 else (maximum (map metaSymbInt metas) + 1)
|
||||||
|
|
||||||
|
ref2exp :: [Var] -> Type -> Ref -> Err Exp
|
||||||
|
ref2exp bounds typ ref = do
|
||||||
|
cont <- contextOfType typ
|
||||||
|
xx0 <- mapM (typeSkeleton . snd) cont
|
||||||
|
let (xxs,cs) = unzip [(length hs, c) | (hs,c) <- xx0]
|
||||||
|
args = [mkAbs xs mExp | i <- xxs, let xs = mkFreshVars i bounds]
|
||||||
|
return $ mkApp ref args
|
||||||
|
-- no refreshment of metas
|
||||||
|
|
||||||
|
type Ref = Exp -- invariant: only Con or Var
|
||||||
|
|
||||||
|
fun2wrap :: [Var] -> ((Fun,Int),Type) -> Exp -> Err Exp
|
||||||
|
fun2wrap oldvars ((fun,i),typ) exp = do
|
||||||
|
cont <- contextOfType typ
|
||||||
|
args <- mapM mkArg (zip [0..] (map snd cont))
|
||||||
|
return $ mkApp (qq fun) args
|
||||||
|
where
|
||||||
|
mkArg (n,c) = do
|
||||||
|
cont <- contextOfType c
|
||||||
|
let vars = mkFreshVars (length cont) oldvars
|
||||||
|
return $ mkAbs vars $ if n==i then exp else mExp
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
mkJustProd cont typ = mkProd (cont,typ,[])
|
||||||
|
|
||||||
|
int2var :: Int -> Ident
|
||||||
|
int2var = zIdent . ('$':) . show
|
||||||
|
|
||||||
|
meta0 :: Meta
|
||||||
|
meta0 = int2meta 0
|
||||||
|
|
||||||
|
termMeta0 :: Term
|
||||||
|
termMeta0 = Meta meta0
|
||||||
|
|
||||||
|
identVar (Vr x) = return x
|
||||||
|
identVar _ = Bad "not a variable"
|
||||||
|
|
||||||
|
|
||||||
|
-- light-weight rename for user interaction
|
||||||
|
|
||||||
|
qualifTerm :: Ident -> Term -> Term
|
||||||
|
qualifTerm m = qualif [] where
|
||||||
|
qualif xs t = case t of
|
||||||
|
Abs x b -> Abs x $ qualif (x:xs) b
|
||||||
|
Prod x a b -> Prod x (qualif xs a) $ qualif (x:xs) b
|
||||||
|
Vr x | notElem x xs -> Q m x
|
||||||
|
Cn c -> Q m c
|
||||||
|
Con c -> QC m c
|
||||||
|
_ -> composSafeOp (qualif xs) t
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user