mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-23 11:42:49 -06:00
top-level toy compiler - far from complete
This commit is contained in:
35
devel/compiler/Compile.hs
Normal file
35
devel/compiler/Compile.hs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
module Compile where
|
||||||
|
|
||||||
|
import AbsSrc
|
||||||
|
import AbsTgt
|
||||||
|
import SMacros
|
||||||
|
import TMacros
|
||||||
|
|
||||||
|
import Eval
|
||||||
|
import Param
|
||||||
|
|
||||||
|
import STM
|
||||||
|
import Env
|
||||||
|
|
||||||
|
import qualified Data.Map as M
|
||||||
|
|
||||||
|
compile :: Grammar -> Env
|
||||||
|
compile (Gr defs) = err error snd $ appSTM (mapM_ compDef defs) emptyEnv
|
||||||
|
|
||||||
|
compDef :: Def -> STM Env ()
|
||||||
|
compDef d = case d of
|
||||||
|
DLin f ty exp -> do
|
||||||
|
val <- eval exp
|
||||||
|
addType f ty
|
||||||
|
addVal f val
|
||||||
|
DOper f ty exp -> do
|
||||||
|
addType f ty
|
||||||
|
addOper f exp
|
||||||
|
DPar p cs -> do
|
||||||
|
v <- sizeParType cs
|
||||||
|
addTypedef p $ TVal $ toInteger $ fst v
|
||||||
|
vals <- allParVals cs
|
||||||
|
addPartype (TBas p) vals
|
||||||
|
mapM_ (uncurry addParVal) (zip vals (map VPar [0..]))
|
||||||
|
DOpty a ty -> do
|
||||||
|
addTypedef a ty
|
||||||
52
devel/compiler/Env.hs
Normal file
52
devel/compiler/Env.hs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
module Env where
|
||||||
|
|
||||||
|
import AbsSrc
|
||||||
|
import AbsTgt
|
||||||
|
|
||||||
|
import STM
|
||||||
|
import qualified Data.Map as M
|
||||||
|
|
||||||
|
data Env = Env {
|
||||||
|
values :: M.Map Ident Val,
|
||||||
|
types :: M.Map Ident Type,
|
||||||
|
opers :: M.Map Ident Exp,
|
||||||
|
typedefs :: M.Map Ident Type,
|
||||||
|
partypes :: M.Map Type [Exp],
|
||||||
|
parvals :: M.Map Exp Val,
|
||||||
|
vars :: M.Map Ident Val
|
||||||
|
--- constrs :: M.Map Ident ([Int] -> Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyEnv = Env M.empty M.empty M.empty M.empty M.empty M.empty M.empty
|
||||||
|
|
||||||
|
lookEnv :: (Show i, Ord i) => (Env -> M.Map i a) -> i -> STM Env a
|
||||||
|
lookEnv field c = do
|
||||||
|
s <- readSTM
|
||||||
|
maybe (raise $ "unknown " ++ show c) return $ M.lookup c $ field s
|
||||||
|
|
||||||
|
addVal :: Ident -> Val -> STM Env ()
|
||||||
|
addVal c v = updateSTM (\env -> (env{values = M.insert c v (values env)}))
|
||||||
|
|
||||||
|
addType :: Ident -> Type -> STM Env ()
|
||||||
|
addType c v = updateSTM (\env -> (env{types = M.insert c v (types env)}))
|
||||||
|
|
||||||
|
addOper :: Ident -> Exp -> STM Env ()
|
||||||
|
addOper c v = updateSTM (\env -> (env{opers = M.insert c v (opers env)}))
|
||||||
|
|
||||||
|
addTypedef :: Ident -> Type -> STM Env ()
|
||||||
|
addTypedef c v = updateSTM (\env -> (env{typedefs = M.insert c v (typedefs env)}))
|
||||||
|
|
||||||
|
addPartype :: Type -> [Exp] -> STM Env ()
|
||||||
|
addPartype c v = updateSTM (\env -> (env{partypes = M.insert c v (partypes env)}))
|
||||||
|
|
||||||
|
addParVal :: Exp -> Val -> STM Env ()
|
||||||
|
addParVal c v = updateSTM (\env -> (env{parvals = M.insert c v (parvals env)}))
|
||||||
|
|
||||||
|
---addEnv :: (Env -> M.Map Ident a) -> Ident -> a -> STM Env ()
|
||||||
|
---addEnv field c v = updateSTM (\env -> (env{field = M.insert c v (field env)},()))
|
||||||
|
|
||||||
|
addVar :: Ident -> STM Env ()
|
||||||
|
addVar x = do
|
||||||
|
s <- readSTM
|
||||||
|
let i = M.size $ vars s
|
||||||
|
updateSTM (\env -> (env{vars = M.insert x (VArg $ toInteger i) (vars env)}))
|
||||||
@@ -2,21 +2,57 @@ module Eval where
|
|||||||
|
|
||||||
import AbsSrc
|
import AbsSrc
|
||||||
import AbsTgt
|
import AbsTgt
|
||||||
|
import SMacros
|
||||||
|
import TMacros
|
||||||
|
|
||||||
import qualified Data.Map as M
|
import ComposOp
|
||||||
|
import STM
|
||||||
|
import Env
|
||||||
|
|
||||||
eval :: Env -> Exp -> Val
|
eval :: Exp -> STM Env Val
|
||||||
eval env e = case e of
|
eval e = case e of
|
||||||
ECon c -> look c
|
EAbs x b -> do
|
||||||
EStr s -> VTok s
|
addVar x ---- adds new VArg i
|
||||||
ECat x y -> VCat (ev x) (ev y)
|
eval b
|
||||||
where
|
EApp _ _ -> do
|
||||||
look = lookCons env
|
let (f,xs) = apps e
|
||||||
ev = eval env
|
xs' <- mapM eval xs
|
||||||
|
case f of
|
||||||
|
ECon c -> checks [
|
||||||
|
do
|
||||||
|
v <- lookEnv values c
|
||||||
|
return $ appVal v xs'
|
||||||
|
,
|
||||||
|
do
|
||||||
|
e <- lookEnv opers c
|
||||||
|
v <- eval e
|
||||||
|
return $ appVal v xs'
|
||||||
|
]
|
||||||
|
ECon c -> lookEnv values c
|
||||||
|
EVar x -> lookEnv vars x
|
||||||
|
ECst _ _ -> lookEnv parvals e
|
||||||
|
EStr s -> return $ VTok s
|
||||||
|
ECat x y -> do
|
||||||
|
x' <- eval x
|
||||||
|
y' <- eval y
|
||||||
|
return $ VCat x' y'
|
||||||
|
ERec fs -> do
|
||||||
|
vs <- mapM eval [e | FExp _ e <- fs]
|
||||||
|
return $ VRec vs
|
||||||
|
|
||||||
data Env = Env {
|
ETab cs -> do
|
||||||
constants :: M.Map Ident Val
|
vs <- mapM eval [e | Cas _ e <- cs] ---- expand and pattern match
|
||||||
}
|
return $ VRec vs
|
||||||
|
|
||||||
|
|
||||||
|
ESel t v -> do
|
||||||
|
t' <- eval t
|
||||||
|
v' <- eval v
|
||||||
|
---- pattern match first
|
||||||
|
return $ compVal [] $ VPro t' v' ---- []
|
||||||
|
|
||||||
|
EPro t v -> do
|
||||||
|
t' <- eval t
|
||||||
|
---- project first
|
||||||
|
return $ VPro t' (VPar 666) ---- lookup label
|
||||||
|
|
||||||
lookCons :: Env -> Ident -> Val
|
|
||||||
lookCons env c = maybe undefined id $ M.lookup c $ constants env
|
|
||||||
|
|||||||
@@ -1,38 +1,34 @@
|
|||||||
type Param = (Id,[Constr])
|
module Param where
|
||||||
type Constr = (Id,[Id])
|
|
||||||
type Source = [Param]
|
|
||||||
type Id = String
|
|
||||||
|
|
||||||
type Target = [(Id,((Int,Int),[Id]))]
|
import AbsSrc
|
||||||
|
import SMacros
|
||||||
|
|
||||||
compile :: Source -> Target
|
import Env
|
||||||
compile src = ctyps ++ incss where
|
import STM
|
||||||
ctyps = map compT src
|
|
||||||
(typs,cons) = unzip src
|
|
||||||
compT (ty,cs) =
|
|
||||||
(ty,((sum [product [size t | t <- ts] | (_,ts) <- cs],length cs),[]))
|
|
||||||
size ty = maybe undefined (fst . fst) $ lookup ty ctyps
|
|
||||||
incss = concat $ map (incs 0) cons
|
|
||||||
incs k cs = case cs of
|
|
||||||
(c,ts):cs2 ->
|
|
||||||
let s = product (map size ts) in (c,((s,k),ts)) : incs (k+s) cs2
|
|
||||||
_ -> []
|
|
||||||
|
|
||||||
newtype Value = V (Id,[Value])
|
sizeParType :: [Constr] -> STM Env (Int,Int)
|
||||||
|
sizeParType cs = do
|
||||||
|
scs <- mapM sizeC cs
|
||||||
|
return (sum scs, length cs)
|
||||||
|
where
|
||||||
|
sizeC (Con c ts) = do
|
||||||
|
ats <- mapM lookParTypeSize ts
|
||||||
|
return $ product ats
|
||||||
|
|
||||||
value :: Target -> Value -> Int
|
lookParTypeSize :: Type -> STM Env Int
|
||||||
value tg (V (f,xs)) = maybe undefined (snd . fst) (lookup f tg) + posit xs where
|
lookParTypeSize ty = case ty of
|
||||||
posit xs =
|
TBas c -> do
|
||||||
sum [value tg x * product [size p | (_,p) <- xs2] |
|
ty' <- lookEnv typedefs c
|
||||||
i <- [0..length xs -1],
|
lookParTypeSize ty'
|
||||||
let (x,_):xs2 = drop i (zip xs args)
|
TVal i -> return $ fromInteger i
|
||||||
]
|
|
||||||
args = maybe undefined snd $ lookup f tg
|
|
||||||
size p = maybe undefined (fst . fst) $ lookup p tg
|
|
||||||
|
|
||||||
ex1 :: Source
|
allParVals :: [Constr] -> STM Env [Exp]
|
||||||
ex1 = [
|
allParVals cs = do
|
||||||
("B",[("T",[]),("F",[])]),
|
ess <- mapM alls cs
|
||||||
("G",[("M",[]),("Fe",[]),("N",[])]),
|
return $ concat ess
|
||||||
("Q",[("Q1",["B"]),("Q2",["B","B"]),("Q3",["B","B","B"])])
|
where
|
||||||
]
|
alls (Con c []) = do
|
||||||
|
return [constr c []]
|
||||||
|
alls (Con c ts) = do
|
||||||
|
ess <- mapM (lookEnv partypes) ts
|
||||||
|
return [constr c es | es <- sequence ess]
|
||||||
|
|||||||
47
devel/compiler/PrEnv.hs
Normal file
47
devel/compiler/PrEnv.hs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
module PrEnv where
|
||||||
|
|
||||||
|
import Env
|
||||||
|
|
||||||
|
import AbsSrc
|
||||||
|
import AbsTgt
|
||||||
|
|
||||||
|
import qualified PrintSrc as S
|
||||||
|
import qualified PrintTgt as T
|
||||||
|
|
||||||
|
import qualified Data.Map as M
|
||||||
|
|
||||||
|
prEnv :: Env -> IO ()
|
||||||
|
prEnv env = do
|
||||||
|
putStrLn "--# values"
|
||||||
|
mapM_ putStrLn
|
||||||
|
[prs c ++ " = " ++ prt val | (c,val) <- M.toList $ values env]
|
||||||
|
putStrLn "--# types"
|
||||||
|
mapM_ putStrLn
|
||||||
|
[prs c ++ " : " ++ prs val | (c,val) <- M.toList $ types env]
|
||||||
|
putStrLn "--# typedefs"
|
||||||
|
mapM_ putStrLn
|
||||||
|
[prs c ++ " = " ++ prs val | (c,val) <- M.toList $ typedefs env]
|
||||||
|
putStrLn "--# partypes"
|
||||||
|
mapM_ putStrLn
|
||||||
|
[prs c ++ " = " ++ unwords (map prs val) | (c,val) <- M.toList $ partypes env]
|
||||||
|
putStrLn "--# parvals"
|
||||||
|
mapM_ putStrLn
|
||||||
|
[prs c ++ " = " ++ prt val | (c,val) <- M.toList $ parvals env]
|
||||||
|
|
||||||
|
prs :: (S.Print a) => a -> String
|
||||||
|
prs = S.printTree
|
||||||
|
|
||||||
|
prt :: (T.Print a) => a -> String
|
||||||
|
prt = T.printTree
|
||||||
|
|
||||||
|
{-
|
||||||
|
data Env = Env {
|
||||||
|
values :: M.Map Ident Val,
|
||||||
|
types :: M.Map Ident Type,
|
||||||
|
opers :: M.Map Ident Exp,
|
||||||
|
typedefs :: M.Map Ident Type,
|
||||||
|
partypes :: M.Map Type [Exp],
|
||||||
|
parvals :: M.Map Exp Val,
|
||||||
|
vars :: M.Map Ident Val
|
||||||
|
}
|
||||||
|
-}
|
||||||
16
devel/compiler/SMacros.hs
Normal file
16
devel/compiler/SMacros.hs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
module SMacros where
|
||||||
|
|
||||||
|
import AbsSrc
|
||||||
|
|
||||||
|
apps :: Exp -> (Exp,[Exp])
|
||||||
|
apps e = (f,reverse xs) where
|
||||||
|
(f,xs) = aps e
|
||||||
|
aps e = case e of
|
||||||
|
EApp f x -> let (f',xs) = aps f in (f',x:xs)
|
||||||
|
_ -> (e,[])
|
||||||
|
|
||||||
|
constr :: Ident -> [Exp] -> Exp
|
||||||
|
constr = ECst
|
||||||
|
|
||||||
|
mkApp :: Exp -> [Exp] -> Exp
|
||||||
|
mkApp f = foldl EApp f
|
||||||
94
devel/compiler/STM.hs
Normal file
94
devel/compiler/STM.hs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
module STM where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
|
||||||
|
-- state monad
|
||||||
|
|
||||||
|
|
||||||
|
-- the Error monad
|
||||||
|
|
||||||
|
-- | like @Maybe@ type with error msgs
|
||||||
|
data Err a = Ok a | Bad String
|
||||||
|
deriving (Read, Show, Eq)
|
||||||
|
|
||||||
|
instance Monad Err where
|
||||||
|
return = Ok
|
||||||
|
fail = Bad
|
||||||
|
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
|
||||||
|
|
||||||
|
-- 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 []
|
||||||
|
|
||||||
|
doUntil :: ErrorMonad m => (a -> Bool) -> [m a] -> m a
|
||||||
|
doUntil cond ms = case ms of
|
||||||
|
a:as -> do
|
||||||
|
v <- a
|
||||||
|
if cond v then return v else doUntil cond as
|
||||||
|
_ -> raise "no result"
|
||||||
|
|
||||||
@@ -36,10 +36,11 @@ ETab. Exp1 ::= "table" "{" [Case] "}" ;
|
|||||||
ETbv. Exp1 ::= "table" "(" Type ")" "{" [Exp] "}" ;
|
ETbv. Exp1 ::= "table" "(" Type ")" "{" [Exp] "}" ;
|
||||||
ECat. Exp ::= Exp "++" Exp1 ;
|
ECat. Exp ::= Exp "++" Exp1 ;
|
||||||
EAbs. Exp ::= "\\" Ident "->" Exp ;
|
EAbs. Exp ::= "\\" Ident "->" Exp ;
|
||||||
|
ECst. Exp2 ::= "(" Ident "@" [Exp] ")" ;
|
||||||
|
|
||||||
coercions Exp 2 ;
|
coercions Exp 2 ;
|
||||||
|
|
||||||
separator Exp ";" ;
|
separator Exp "," ;
|
||||||
|
|
||||||
FExp. Assign ::= Ident "=" Exp ;
|
FExp. Assign ::= Ident "=" Exp ;
|
||||||
|
|
||||||
|
|||||||
16
devel/compiler/TMacros.hs
Normal file
16
devel/compiler/TMacros.hs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
module TMacros where
|
||||||
|
|
||||||
|
import AbsTgt
|
||||||
|
|
||||||
|
appVal :: Val -> [Val] -> Val
|
||||||
|
appVal v vs = compVal vs v
|
||||||
|
|
||||||
|
compVal :: [Val] -> Val -> Val
|
||||||
|
compVal args = comp where
|
||||||
|
comp val = case val of
|
||||||
|
VRec vs -> VRec $ map comp vs
|
||||||
|
VPro r p -> case (comp r, comp p) of
|
||||||
|
(VRec vs, VPar i) -> vs !! fromInteger i
|
||||||
|
VArg i -> args !! fromInteger i
|
||||||
|
VCat x y -> VCat (comp x) (comp y)
|
||||||
|
_ -> val
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Tg. Object ::= [Fun] ;
|
Tg. Object ::= [Fun] ;
|
||||||
|
|
||||||
FVal. Fun ::= Ident "=" Val ;
|
FVal. Fun ::= Id "=" Val ;
|
||||||
|
|
||||||
terminator Fun ";" ;
|
terminator Fun ";" ;
|
||||||
|
|
||||||
@@ -14,3 +14,5 @@ VPar. Val ::= Integer ;
|
|||||||
VCat. Val ::= "(" Val Val ")" ;
|
VCat. Val ::= "(" Val Val ")" ;
|
||||||
|
|
||||||
terminator Val "," ;
|
terminator Val "," ;
|
||||||
|
|
||||||
|
token Id (letter | '_') (letter | digit | '_' | '\'')* ;
|
||||||
|
|||||||
34
devel/compiler/Top.hs
Normal file
34
devel/compiler/Top.hs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import IO ( stdin, hGetContents )
|
||||||
|
import System ( getArgs, getProgName )
|
||||||
|
|
||||||
|
import LexSrc
|
||||||
|
import ParSrc
|
||||||
|
import SkelSrc
|
||||||
|
import PrintSrc
|
||||||
|
import AbsSrc
|
||||||
|
|
||||||
|
import Compile
|
||||||
|
import PrEnv
|
||||||
|
|
||||||
|
import ErrM
|
||||||
|
|
||||||
|
type ParseFun a = [Token] -> Err a
|
||||||
|
|
||||||
|
myLLexer = myLexer
|
||||||
|
|
||||||
|
runFile :: ParseFun Grammar -> FilePath -> IO ()
|
||||||
|
runFile p f = readFile f >>= run p
|
||||||
|
|
||||||
|
run :: ParseFun Grammar -> String -> IO ()
|
||||||
|
run p s = let ts = myLLexer s in case p ts of
|
||||||
|
Bad s -> do putStrLn "Parse Failed...\n"
|
||||||
|
putStrLn s
|
||||||
|
Ok tree -> prEnv $ compile tree
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do args <- getArgs
|
||||||
|
case args of
|
||||||
|
fs -> mapM_ (runFile pGrammar) fs
|
||||||
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
param Num = Sg | Pl ;
|
param Num = Sg | Pl ;
|
||||||
param Gen = Masc | Fem ;
|
param Gen = Masc | Fem ;
|
||||||
|
|
||||||
|
param AG = A Num Gen ;
|
||||||
|
|
||||||
oper Agr = {g : Gen ; n : Num} ;
|
oper Agr = {g : Gen ; n : Num} ;
|
||||||
|
|
||||||
oper CN = {s : Num -> Str ; g : Gen} ;
|
oper CN = {s : Num -> Str ; g : Gen} ;
|
||||||
@@ -9,7 +11,7 @@ oper NP = {s : Str ; a : Agr} ;
|
|||||||
oper artDef : Gen -> Str = \g -> table {
|
oper artDef : Gen -> Str = \g -> table {
|
||||||
(Masc) => "le" ;
|
(Masc) => "le" ;
|
||||||
(Fem) => "la"
|
(Fem) => "la"
|
||||||
} ! g ;
|
} ! $g ;
|
||||||
|
|
||||||
|
|
||||||
lin Voiture : CN = {
|
lin Voiture : CN = {
|
||||||
@@ -17,15 +19,18 @@ lin Voiture : CN = {
|
|||||||
(Sg) => "voiture" ;
|
(Sg) => "voiture" ;
|
||||||
(Pl) => "voitures"
|
(Pl) => "voitures"
|
||||||
} ;
|
} ;
|
||||||
g = Fem
|
g = (Fem@)
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
{-
|
||||||
lin Bus : CN = {
|
lin Bus : CN = {
|
||||||
s = table {$x => "bus"} ;
|
s = table {$x => "bus"} ;
|
||||||
g = Masc
|
g = (Masc@)
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
lin Def : CN -> NP = \cn -> {
|
lin Def : CN -> NP = \cn -> {
|
||||||
s = artDef cn.g ++ cn.s ! Sg ;
|
s = artDef $cn.g ++ $cn.s ! (Sg@) ;
|
||||||
a = {g = cn.g ; n = Sg}
|
a = {g = $cn.g ; n = (Sg@)}
|
||||||
} ;
|
} ;
|
||||||
|
-}
|
||||||
Reference in New Issue
Block a user