1
0
forked from GitHub/gf-core

steps towards an NLG language

This commit is contained in:
Krasimir Angelov
2024-04-07 10:39:43 +02:00
parent 81717e7822
commit f637abe92e
6 changed files with 162 additions and 141 deletions

View File

@@ -395,12 +395,12 @@ data Term =
| FV [Term] -- ^ alternatives in free variation: @variants { s ; ... }@ | FV [Term] -- ^ alternatives in free variation: @variants { s ; ... }@
| Markup Ident [(Ident,Term)] [Term]
| Alts Term [(Term, Term)] -- ^ alternatives by prefix: @pre {t ; s\/c ; ...}@ | Alts Term [(Term, Term)] -- ^ alternatives by prefix: @pre {t ; s\/c ; ...}@
| Strs [Term] -- ^ conditioning prefix strings: @strs {s ; ...}@ | Strs [Term] -- ^ conditioning prefix strings: @strs {s ; ...}@
| TSymCat Int LIndex [(LIndex,(Ident,Type))] | TSymCat Int LIndex [(LIndex,(Ident,Type))]
| TSymVar Int Int | TSymVar Int Int
| OpenTag Ident [Assign] -- used internally in the parser
| CloseTag Ident -- used internally in the parser
deriving (Show, Eq, Ord) deriving (Show, Eq, Ord)
-- | Patterns -- | Patterns

View File

@@ -2,8 +2,8 @@
{ {
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP #-}
module GF.Grammar.Lexer module GF.Grammar.Lexer
( Token(..), Posn(..) ( Lang(..), Token(..), Posn(..)
, P, runP, runPartial, token, lexer, getPosn, failLoc , P, runP, runLangP, runPartial, token, lexer, getPosn, failLoc
, isReservedWord , isReservedWord
) where ) where
@@ -17,7 +17,7 @@ import qualified Data.ByteString.Internal as BS(w2c)
import qualified Data.ByteString.UTF8 as UTF8 import qualified Data.ByteString.UTF8 as UTF8
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.Word(Word8) import Data.Word(Word8)
import Data.Char(readLitChar,isSpace) import Data.Char(readLitChar,isSpace,isAlphaNum)
import Data.Maybe(isJust) import Data.Maybe(isJust)
import qualified Control.Monad.Fail as Fail import qualified Control.Monad.Fail as Fail
} }
@@ -31,7 +31,10 @@ $i = [$l $d _ '] -- identifier character
$u = [.\n] -- universal: any character $u = [.\n] -- universal: any character
@rsyms = -- symbols and non-identifier-like reserved words @rsyms = -- symbols and non-identifier-like reserved words
\; | \= | \{ | \} | \( | \) | \~ | \* \* | \: | \- \> | \, | \[ | \] | \- | \. | \| | \% | \? | \> | \@ | \# | \! | \* | \+ | \+ \+ | \\ | \\\\ | \= \> | \_ | \$ | \/ | \: \= | \: \: \= \; | \= | \{ | \} | \( | \) | \~ | \* \* | \: | \- \> | \, | \[ | \] | \- | \. | \| | \% | \? | \< | \> | \@ | \# | \! | \* | \+ | \+ \+ | \\ | \\\\ | \= \> | \_ | \$ | \/ | \: \= | \: \: \=
@ident =
(\_ | $l)($l | $d | \_ | \')*
:- :-
"--" [.]* ; -- Toss single line comments "--" [.]* ; -- Toss single line comments
@@ -39,11 +42,39 @@ $u = [.\n] -- universal: any character
$white+ ; $white+ ;
@rsyms { tok ident } @rsyms { tok ident }
\< { \_ _ s -> if start_of_tag (BS.tail s) \< $white* @ident $white* (\/ | \>)
then T_less_tag { \lang inp@(AI pos s) inp' _ ->
else T_less } let inp0 = AI (alexMove pos '<') (BS.tail s)
in case lang of {
NLG -> case getTag inp0 of {
Just (tag,inp') -> POk (inp,inp') (T_open_tag tag) ;
Nothing -> PFailed pos "matching the html tag failed"
} ;
_ -> POk (inp,inp0) T_less
} }
\< $white* @ident $white+ @ident $white* \=
{ \lang inp@(AI pos s) inp' _ ->
let inp0 = AI (alexMove pos '<') (BS.tail s)
in case lang of {
NLG -> case getTag inp0 of {
Just (tag,inp') -> if tag == identS "let"
then POk (inp,inp0) T_less
else POk (inp,inp') (T_open_tag tag) ;
Nothing -> PFailed pos "matching the html tag failed"
} ;
_ -> POk (inp,inp0) T_less
} }
\< \/ $white* @ident { \lang inp@(AI pos s) inp' _ ->
case lang of {
NLG -> case getTag (AI (alexMove (alexMove pos '<') '/') (BS.drop 2 s)) of {
Just (tag,inp') -> POk (inp,inp') (T_close_tag tag) ;
Nothing -> PFailed pos "matching the html tag failed"
} ;
_ -> let inp0 = AI (alexMove pos '<') (BS.tail s)
in POk (inp,inp0) T_less
} }
\' ([. # [\' \\ \n]] | (\\ (\' | \\)))+ \' { tok (T_Ident . identS . unescapeInitTail . unpack) } \' ([. # [\' \\ \n]] | (\\ (\' | \\)))+ \' { tok (T_Ident . identS . unescapeInitTail . unpack) }
(\_ | $l)($l | $d | \_ | \')* { tok ident } @ident { tok ident }
\" ([$u # [\" \\ \n]] | (\\ (\" | \\ | \' | n | t | $d+)))* \" { tok (T_String . unescapeInitTail . unpack) } \" ([$u # [\" \\ \n]] | (\\ (\" | \\ | \' | n | t | $d+)))* \" { tok (T_String . unescapeInitTail . unpack) }
@@ -53,11 +84,10 @@ $white+ ;
{ {
unpack = UTF8.toString unpack = UTF8.toString
--unpack = id
ident = res T_Ident . identC . rawIdentC ident = res T_Ident . identC . rawIdentC
tok f p len s = f (UTF8.take len s) tok f _ inp@(AI _ s) inp' len = POk (inp,inp') (f (UTF8.take len s))
data Token data Token
= T_exclmark = T_exclmark
@@ -78,7 +108,6 @@ data Token
| T_colon | T_colon
| T_semicolon | T_semicolon
| T_less | T_less
| T_less_tag
| T_equal | T_equal
| T_big_rarrow | T_big_rarrow
| T_great | T_great
@@ -138,6 +167,8 @@ data Token
| T_Integer Integer -- integer literals | T_Integer Integer -- integer literals
| T_Double Double -- double precision float literals | T_Double Double -- double precision float literals
| T_Ident Ident | T_Ident Ident
| T_open_tag Ident
| T_close_tag Ident
| T_EOF | T_EOF
deriving Show -- debug deriving Show -- debug
@@ -171,6 +202,7 @@ resWords = Map.fromList
, b ";" T_semicolon , b ";" T_semicolon
, b "=" T_equal , b "=" T_equal
, b "=>" T_big_rarrow , b "=>" T_big_rarrow
, b "<" T_less
, b ">" T_great , b ">" T_great
, b "?" T_questmark , b "?" T_questmark
, b "[" T_obrack , b "[" T_obrack
@@ -251,20 +283,14 @@ alexMove (Pn l c) '\n' = Pn (l+1) 1
alexMove (Pn l c) _ = Pn l (c+1) alexMove (Pn l c) _ = Pn l (c+1)
alexGetByte :: AlexInput -> Maybe (Word8,AlexInput) alexGetByte :: AlexInput -> Maybe (Word8,AlexInput)
alexGetByte (AI p _ s) = alexGetByte (AI p s) =
case WBS.uncons s of case WBS.uncons s of
Nothing -> Nothing Nothing -> Nothing
Just (w,s) -> Just (w,s) ->
let p' = alexMove p c let p' = alexMove p (BS.w2c w)
c = BS.w2c w in p' `seq` Just (w, (AI p' s))
in p' `seq` Just (w, (AI p' c s))
{-
-- Not used by this lexer:
alexInputPrevChar :: AlexInput -> Char
alexInputPrevChar (AI p c s) = c
-}
data AlexInput = AI {-# UNPACK #-} !Posn -- current position, data AlexInput = AI {-# UNPACK #-} !Posn -- current position,
{-# UNPACK #-} !Char -- previous char
{-# UNPACK #-} !BS.ByteString -- current input string {-# UNPACK #-} !BS.ByteString -- current input string
type AlexInput2 = (AlexInput,AlexInput) type AlexInput2 = (AlexInput,AlexInput)
@@ -274,7 +300,9 @@ data ParseResult a
| PFailed Posn -- The position of the error | PFailed Posn -- The position of the error
String -- The error message String -- The error message
newtype P a = P { unP :: AlexInput2 -> ParseResult a } data Lang = GF | BNFC | NLG
newtype P a = P { unP :: Lang -> AlexInput2 -> ParseResult a }
instance Functor P where instance Functor P where
fmap = liftA fmap = liftA
@@ -284,10 +312,10 @@ instance Applicative P where
(<*>) = ap (<*>) = ap
instance Monad P where instance Monad P where
return a = a `seq` (P $ \s -> POk s a) return a = a `seq` (P $ \_ s -> POk s a)
(P m) >>= k = P $ \ s -> case m s of (P m) >>= k = P $ \l s -> case m l s of
POk s a -> unP (k a) s POk s a -> unP (k a) l s
PFailed posn err -> PFailed posn err PFailed posn err -> PFailed posn err
#if !(MIN_VERSION_base(4,13,0)) #if !(MIN_VERSION_base(4,13,0))
-- Monad(fail) will be removed in GHC 8.8+ -- Monad(fail) will be removed in GHC 8.8+
@@ -295,24 +323,27 @@ instance Monad P where
#endif #endif
instance Fail.MonadFail P where instance Fail.MonadFail P where
fail msg = P $ \(_,AI posn _ _) -> PFailed posn msg fail msg = P $ \_ (_,AI posn _) -> PFailed posn msg
runP :: P a -> BS.ByteString -> Either (Posn,String) a runP :: P a -> BS.ByteString -> Either (Posn,String) a
runP p bs = snd <$> runP' p (Pn 1 0,bs) runP p bs = snd <$> runP' GF p (Pn 1 0,bs)
runPartial p s = conv <$> runP' p (Pn 1 0,UTF8.fromString s) runLangP :: Lang -> P a -> BS.ByteString -> Either (Posn,String) a
runLangP lang p bs = snd <$> runP' lang p (Pn 1 0,bs)
runPartial p s = conv <$> runP' GF p (Pn 1 0,UTF8.fromString s)
where conv ((pos,rest),x) = (UTF8.toString rest,x) where conv ((pos,rest),x) = (UTF8.toString rest,x)
runP' (P f) (pos,txt) = runP' lang (P f) (pos,txt) =
case f (dup (AI pos ' ' txt)) of case f lang (dup (AI pos txt)) of
POk (AI pos _ rest,_) x -> Right ((pos,rest),x) POk (AI pos rest,_) x -> Right ((pos,rest),x)
PFailed pos msg -> Left (pos,msg) PFailed pos msg -> Left (pos,msg)
dup x = (x,x) dup x = (x,x)
failLoc :: Posn -> String -> P a failLoc :: Posn -> String -> P a
failLoc pos msg = P $ \_ -> PFailed pos msg failLoc pos msg = P $ \_ _ -> PFailed pos msg
lexer :: (Token -> P a) -> P a lexer :: (Token -> P a) -> P a
lexer cont = cont=<<token lexer cont = cont=<<token
@@ -320,58 +351,29 @@ lexer cont = cont=<<token
token :: P Token token :: P Token
token = P go token = P go
where where
go ai2@(_,inp@(AI pos _ str)) = go lang (_,inp) =
case alexScan inp 0 of case alexScan inp 0 of
AlexEOF -> POk (inp,inp) T_EOF AlexEOF -> POk (inp,inp) T_EOF
AlexError (AI pos _ _) -> PFailed pos "lexical error" AlexError (AI pos _) -> PFailed pos "lexical error"
AlexSkip inp' len -> {-trace (show len) $-} go (inp,inp') AlexSkip inp' len -> go lang (inp,inp')
AlexToken inp' len act -> POk (inp,inp') (act pos len str) AlexToken inp' len act -> act lang inp inp' len
start_of_tag s = isJust (match s) getTag inp = space inp
where where
match s = do space inp = do
s <- matchSpace s (w,inp') <- alexGetByte inp
(char s '/' if isSpace (BS.w2c w)
`mplus` then space inp'
do s <- matchIdent s else ident [] inp
s <- matchSpace s
(char s '/'
`mplus`
do s <- matchIdent s
s <- matchSpace s
char s '='))
matchSpace s ident cs inp = do
| BS.null s = Just s (w,inp') <- alexGetByte inp
| isSpace (BS.head s) = matchSpace (BS.tail s) let c = BS.w2c w
| otherwise = Just s if isAlphaNum c || c == '_'
then ident (c:cs) inp'
init = else return (identS (reverse cs),inp)
BS.pack "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"
rest =
BS.append init (BS.pack "0123456789'")
char s c
| BS.null s = Nothing
| BS.head s == c = Just (BS.tail s)
| otherwise = Nothing
matchIdent s
| BS.null s = Nothing
| BS.elem (BS.head s) init = matchRest s 1 (BS.tail s)
| otherwise = Nothing
matchRest s0 i s
| BS.null s = checkResWord (BS.take i s0) s
| BS.elem (BS.head s) rest = matchRest s0 (i+1) (BS.tail s)
| otherwise = checkResWord (BS.take i s0) s
checkResWord w s =
case Map.lookup (identC (rawIdentC w)) resWords of
Just t -> Nothing
Nothing -> Just s
getPosn :: P Posn getPosn :: P Posn
getPosn = P $ \ai2@(_,inp@(AI pos _ _)) -> POk ai2 pos getPosn = P $ \_ ai2@(_,inp@(AI pos _)) -> POk ai2 pos
} }

View File

@@ -2,13 +2,14 @@
{ {
{-# OPTIONS -fno-warn-overlapping-patterns #-} {-# OPTIONS -fno-warn-overlapping-patterns #-}
module GF.Grammar.Parser module GF.Grammar.Parser
( P, runP, runPartial ( P, runP, Lang(..), runLangP, runPartial, Posn(..)
, pModDef , pModDef
, pModHeader , pModHeader
, pTerm , pTerm
, pTopDef , pTopDef
, pBNFCRules , pBNFCRules
, pEBNFRules , pEBNFRules
, pNLG
) where ) where
import GF.Infra.Ident import GF.Infra.Ident
@@ -33,6 +34,7 @@ import qualified Data.Map as Map
%partial pTerm Exp %partial pTerm Exp
%name pBNFCRules ListCFRule %name pBNFCRules ListCFRule
%name pEBNFRules ListEBNFRule %name pEBNFRules ListEBNFRule
%name pNLG NLG
-- no lexer declaration -- no lexer declaration
%monad { P } { >>= } { return } %monad { P } { >>= } { return }
@@ -59,7 +61,6 @@ import qualified Data.Map as Map
':' { T_colon } ':' { T_colon }
';' { T_semicolon } ';' { T_semicolon }
'<' { T_less } '<' { T_less }
'<tag' { T_less_tag }
'=' { T_equal } '=' { T_equal }
'=>' { T_big_rarrow} '=>' { T_big_rarrow}
'>' { T_great } '>' { T_great }
@@ -118,6 +119,8 @@ Integer { (T_Integer $$) }
Double { (T_Double $$) } Double { (T_Double $$) }
String { (T_String $$) } String { (T_String $$) }
Ident { (T_Ident $$) } Ident { (T_Ident $$) }
'<tag' { (T_open_tag $$) }
'</tag' { (T_close_tag $$) }
%% %%
@@ -271,10 +274,10 @@ ParamDef
OperDef :: { [(Ident,Info)] } OperDef :: { [(Ident,Info)] }
OperDef OperDef
: Posn LhsNames ':' Exp Posn { [(i, info) | i <- $2, info <- mkOverload (Just (mkL $1 $5 $4)) Nothing ] } : Posn LhsNames ':' Exp ';' Posn { [(i, info) | i <- $2, info <- mkOverload (Just (mkL $1 $6 $4)) Nothing ] }
| Posn LhsNames '=' Exp Posn { [(i, info) | i <- $2, info <- mkOverload Nothing (Just (mkL $1 $5 $4))] } | Posn LhsNames '=' Markup Posn { [(i, info) | i <- $2, info <- mkOverload Nothing (Just (mkL $1 $5 $4))] }
| Posn LhsName ListArg '=' Exp Posn { [(i, info) | i <- [$2], info <- mkOverload Nothing (Just (mkL $1 $6 (mkAbs $3 $5)))] } | Posn LhsName ListArg '=' Markup Posn { [(i, info) | i <- [$2], info <- mkOverload Nothing (Just (mkL $1 $6 (mkAbs $3 $5)))] }
| Posn LhsNames ':' Exp '=' Exp Posn { [(i, info) | i <- $2, info <- mkOverload (Just (mkL $1 $7 $4)) (Just (mkL $1 $7 $6))] } | Posn LhsNames ':' Exp '=' Markup Posn { [(i, info) | i <- $2, info <- mkOverload (Just (mkL $1 $7 $4)) (Just (mkL $1 $7 $6))] }
LinDef :: { [(Ident,Info)] } LinDef :: { [(Ident,Info)] }
LinDef LinDef
@@ -315,8 +318,8 @@ ListDefDef
ListOperDef :: { [(Ident,Info)] } ListOperDef :: { [(Ident,Info)] }
ListOperDef ListOperDef
: OperDef ';' { $1 } : OperDef { $1 }
| OperDef ';' ListOperDef { $1 ++ $3 } | OperDef ListOperDef { $1 ++ $2 }
ListCatDef :: { [(Ident,Info)] } ListCatDef :: { [(Ident,Info)] }
ListCatDef ListCatDef
@@ -383,11 +386,17 @@ LocDef
| ListIdent '=' Exp { [(lab,Nothing,Just $3) | lab <- $1] } | ListIdent '=' Exp { [(lab,Nothing,Just $3) | lab <- $1] }
| ListIdent ':' Exp '=' Exp { [(lab,Just $3,Just $5) | lab <- $1] } | ListIdent ':' Exp '=' Exp { [(lab,Just $3,Just $5) | lab <- $1] }
LocMarkupDef :: { [(Ident, Maybe Type, Maybe Term)] }
LocMarkupDef
: ListIdent '=' Tag { [(lab,Nothing,Just $3) | lab <- $1] }
| ListIdent ':' Exp '=' Tag { [(lab,Just $3,Just $5) | lab <- $1] }
ListLocDef :: { [(Ident, Maybe Type, Maybe Term)] } ListLocDef :: { [(Ident, Maybe Type, Maybe Term)] }
ListLocDef ListLocDef
: {- empty -} { [] } : {- empty -} { [] }
| LocDef { $1 } | LocDef { $1 }
| LocDef ';' ListLocDef { $1 ++ $3 } | LocMarkupDef ListLocDef { $1 ++ $2 }
| LocDef ';' ListLocDef { $1 ++ $3 }
Exp :: { Term } Exp :: { Term }
Exp Exp
@@ -402,6 +411,9 @@ Exp
| 'let' ListLocDef 'in' Exp {% | 'let' ListLocDef 'in' Exp {%
do defs <- mapM tryLoc $2 do defs <- mapM tryLoc $2
return $ mkLet defs $4 } return $ mkLet defs $4 }
| 'let' ListLocDef 'in' Tag {%
do defs <- mapM tryLoc $2
return $ mkLet defs $4 }
| Exp3 'where' '{' ListLocDef '}' {% | Exp3 'where' '{' ListLocDef '}' {%
do defs <- mapM tryLoc $4 do defs <- mapM tryLoc $4
return $ mkLet defs $1 } return $ mkLet defs $1 }
@@ -432,9 +444,7 @@ Exp3
Exp4 :: { Term } Exp4 :: { Term }
Exp4 Exp4
: Exp4 Exp5 {% case $2 of : Exp4 Exp5 { App $1 $2 }
CloseTag id -> mkTag id $1 Empty
_ -> return (App $1 $2) }
| Exp4 '{' Exp '}' { App $1 (ImplArg $3) } | Exp4 '{' Exp '}' { App $1 (ImplArg $3) }
| 'case' Exp 'of' '{' ListCase '}' { let annot = case $2 of | 'case' Exp 'of' '{' ListCase '}' { let annot = case $2 of
Typed _ t -> TTyped t Typed _ t -> TTyped t
@@ -471,18 +481,6 @@ Exp6
| '<' ListTupleComp '>' { R (tuple2record $2) } | '<' ListTupleComp '>' { R (tuple2record $2) }
| '<' Exp ':' Exp '>' { Typed $2 $4 } | '<' Exp ':' Exp '>' { Typed $2 $4 }
| '(' Exp ')' { $2 } | '(' Exp ')' { $2 }
| '<tag' Ident Attributes '>' { OpenTag $2 $3 }
| '<tag' '/' Ident '>' { CloseTag $3 }
| '<tag' Ident Attributes '/' '>' { markup $2 $3 Empty }
Attributes :: { [Assign] }
Attributes
: { [] }
| Attribute Attributes { $1:$2 }
Attribute :: { Assign }
Attribute
: Ident '=' Exp6 { assign (ident2label $1) $3 }
ListExp :: { [Term] } ListExp :: { [Term] }
ListExp ListExp
@@ -703,6 +701,42 @@ ERHS3 :: { ERHS }
| Ident { ENonTerm (showIdent $1,[]) } | Ident { ENonTerm (showIdent $1,[]) }
| '(' ERHS0 ')' { $2 } | '(' ERHS0 ')' { $2 }
NLG :: { Map.Map Ident Info }
: ListNLGDef { Map.fromList $1 }
| Posn Tag Posn { Map.singleton (identS "main") (ResOper Nothing (Just (mkL $1 $3 (Abs Explicit (identS "qid") $2)))) }
| Posn Exp Posn { Map.singleton (identS "main") (ResOper Nothing (Just (mkL $1 $3 (Abs Explicit (identS "qid") $2)))) }
ListNLGDef :: { [(Ident,Info)] }
ListNLGDef
: {- empty -} { [] }
| 'oper' OperDef ListNLGDef { $2 ++ $3 }
Markup :: { Term }
Markup
: Tag { $1 }
| Exp ';' { $1 }
Tag :: { Term }
Tag
: '<tag' Attributes '>' ListMarkup '</tag' '>' {% if $1 == $5
then return (Markup $1 $2 $4)
else fail ("Unmatched closing tag " ++ showIdent $1) }
| '<tag' Attributes '/' '>' { Markup $1 $2 [] }
ListMarkup :: { [Term] }
: { [] }
| Exp { [$1] }
| Markup ListMarkup { $1 : $2 }
Attributes :: { [(Ident,Term)] }
Attributes
: { [] }
| Attribute Attributes { $1:$2 }
Attribute :: { (Ident,Term) }
Attribute
: Ident '=' Exp6 { ($1,$3) }
ModuleName :: { ModuleName } ModuleName :: { ModuleName }
: Ident { MN $1 } : Ident { MN $1 }
@@ -828,35 +862,4 @@ mkAlts cs = case cs of
mkL :: Posn -> Posn -> x -> L x mkL :: Posn -> Posn -> x -> L x
mkL (Pn l1 _) (Pn l2 _) x = L (Local l1 l2) x mkL (Pn l1 _) (Pn l2 _) x = L (Local l1 l2) x
mkTag ident (App t1 t2) conc =
case match ident t2 of
Just attrs -> fmap (App t1) (mkTag ident t2 conc)
Nothing -> let t = App (Q (cPredef, (identS "linearize"))) t2
in mkTag ident t1 $ case conc of
Empty -> t
_ -> C t conc
mkTag ident t conc =
case match ident t of
Just attrs -> return (markup ident attrs conc)
Nothing -> fail ("Unmatched closing tag " ++ showIdent ident)
match ident (OpenTag ident' attrs)
| ident == ident' = Just attrs
match ident (R [(lbl,(Nothing,Vr ident'))])
| lbl == ident2label (identS "p1") && ident == ident'
= Just []
match ident _ = Nothing
markup ident attrs content =
App
(App
(App
(Q (cPredef, (identS "markup")))
(R attrs)
)
(K (showIdent ident))
)
content
} }

View File

@@ -33,6 +33,7 @@ cSOFT_BIND = identS "SOFT_BIND"
cSOFT_SPACE = identS "SOFT_SPACE" cSOFT_SPACE = identS "SOFT_SPACE"
cCAPIT = identS "CAPIT" cCAPIT = identS "CAPIT"
cALL_CAPIT = identS "ALL_CAPIT" cALL_CAPIT = identS "ALL_CAPIT"
cHtml = identS "Html"
isPredefCat :: Ident -> Bool isPredefCat :: Ident -> Bool
isPredefCat c = elem c [cInt,cString,cFloat] isPredefCat c = elem c [cInt,cString,cFloat]

View File

@@ -24,7 +24,7 @@ module GF.Grammar.Printer
) where ) where
import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint import Prelude hiding ((<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
import PGF2(Literal(..)) import PGF2(Literal(..),pgfFilePath)
import PGF2.Transactions(SeqId) import PGF2.Transactions(SeqId)
import GF.Infra.Ident import GF.Infra.Ident
import GF.Infra.Option import GF.Infra.Option
@@ -84,6 +84,8 @@ ppModule q (mn, ModInfo mtype mstat opts exts with opens _ _ mseqs jments) =
ppExtends (id,MIExcept incs) = id <+> '-' <+> brackets (commaPunct pp incs) ppExtends (id,MIExcept incs) = id <+> '-' <+> brackets (commaPunct pp incs)
ppWith (id,ext,opens) = ppExtends (id,ext) <+> "with" <+> commaPunct ppInstSpec opens ppWith (id,ext,opens) = ppExtends (id,ext) <+> "with" <+> commaPunct ppInstSpec opens
ppModule q (mn, ModPGF pgf) =
"pgf" <+> mn <+> '=' <+> show (pgfFilePath pgf)
ppOptions opts = ppOptions opts =
"flags" $$ "flags" $$
@@ -249,6 +251,11 @@ ppTerm q d (Typed e t) = '<' <> ppTerm q 0 e <+> ':' <+> ppTerm q 0 t <> '>'
ppTerm q d (ImplArg e) = braces (ppTerm q 0 e) ppTerm q d (ImplArg e) = braces (ppTerm q 0 e)
ppTerm q d (ELincat cat t) = prec d 4 ("lincat" <+> cat <+> ppTerm q 5 t) ppTerm q d (ELincat cat t) = prec d 4 ("lincat" <+> cat <+> ppTerm q 5 t)
ppTerm q d (ELin cat t) = prec d 4 ("lin" <+> cat <+> ppTerm q 5 t) ppTerm q d (ELin cat t) = prec d 4 ("lin" <+> cat <+> ppTerm q 5 t)
ppTerm q d (Markup tag attrs children)
| null children = pp "<" <> pp tag <+> hsep (map (ppMarkupAttr q) attrs) <> pp "/>"
| otherwise = pp "<" <> pp tag <+> hsep (map (ppMarkupAttr q) attrs) <> pp ">" $$
nest 3 (ppMarkupChildren q children) $$
pp "</" <> pp tag <> pp ">"
ppTerm q d (TSymCat i r rs) = pp '<' <> pp i <> pp ',' <> ppLinFun (pp.fst) r rs <> pp '>' ppTerm q d (TSymCat i r rs) = pp '<' <> pp i <> pp ',' <> ppLinFun (pp.fst) r rs <> pp '>'
ppTerm q d (TSymVar i r) = pp '<' <> pp i <> pp ',' <> pp '$' <> pp r <> pp '>' ppTerm q d (TSymVar i r) = pp '<' <> pp i <> pp ',' <> pp '$' <> pp r <> pp '>'
@@ -341,6 +348,16 @@ ppAltern q (x,y) = ppTerm q 0 x <+> '/' <+> ppTerm q 0 y
ppParams q ps = fsep (intersperse (pp '|') (map (ppParam q) ps)) ppParams q ps = fsep (intersperse (pp '|') (map (ppParam q) ps))
ppParam q (id,cxt) = id <+> hsep (map (ppDDecl q) cxt) ppParam q (id,cxt) = id <+> hsep (map (ppDDecl q) cxt)
ppMarkupAttr q (id,e) =
id <> pp '=' <> ppTerm q 5 e
ppMarkupChildren q [t] = ppTerm q 0 t
ppMarkupChildren q (t:ts) =
(case t of
Markup {} -> ppTerm q 0 t
_ -> ppTerm q 0 t <> ';') $$
ppMarkupChildren q ts
ppSeqId :: SeqId -> Doc ppSeqId :: SeqId -> Doc
ppSeqId seqid = 'S' <> pp seqid ppSeqId seqid = 'S' <> pp seqid

View File

@@ -82,8 +82,6 @@ library
GF.Infra.Option GF.Infra.Option
GF.Infra.UseIO GF.Infra.UseIO
GF.Infra.BuildInfo GF.Infra.BuildInfo
other-modules:
GF.Support GF.Support
GF.Text.Pretty GF.Text.Pretty
GF.Text.Lexing GF.Text.Lexing