/-----------------------------------------------------------------------------
The Grammar data type.
(c) 1993-2001 Andy Gill, Simon Marlow
>
> module Happy.Grammar (
> Name,
>
> Production(..), Grammar(..),
> Priority(..),
> Assoc(..),
> Pragmas(..), ErrorHandlerType(..),
>
> errorName, errorTok, startName, dummyName, firstStartTok, dummyTok,
> eofName, epsilonTok,
>
> mapDollarDollar
> ) where
> import Data.Array
> import Data.Char (isAlphaNum)
> type Name = Int
> data Production
> = Production Name [Name] (String,[Int]) Priority
> deriving Int -> Production -> ShowS
[Production] -> ShowS
Production -> String
(Int -> Production -> ShowS)
-> (Production -> String)
-> ([Production] -> ShowS)
-> Show Production
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Production -> ShowS
showsPrec :: Int -> Production -> ShowS
$cshow :: Production -> String
show :: Production -> String
$cshowList :: [Production] -> ShowS
showList :: [Production] -> ShowS
Show
> data Grammar
> = Grammar {
> Grammar -> [Production]
productions :: [Production],
> Grammar -> Int -> Production
lookupProdNo :: Int -> Production,
> Grammar -> Int -> [Int]
lookupProdsOfName :: Name -> [Int],
> Grammar -> [(Int, String)]
token_specs :: [(Name,String)],
> Grammar -> [Int]
terminals :: [Name],
> Grammar -> [Int]
non_terminals :: [Name],
> Grammar -> [(String, Int, Int, Bool)]
starts :: [(String,Name,Name,Bool)],
> Grammar -> Array Int (Maybe String)
types :: Array Int (Maybe String),
> Grammar -> Array Int String
token_names :: Array Int String,
> Grammar -> Int
first_nonterm :: Name,
> Grammar -> Int
first_term :: Name,
> Grammar -> Int
eof_term :: Name,
> Grammar -> [(Int, Priority)]
priorities :: [(Name,Priority)],
> Grammar -> [(String, String)]
attributes :: [(String,String)],
> Grammar -> String
attributetype :: String
> }
> instance Show Grammar where
> showsPrec :: Int -> Grammar -> ShowS
showsPrec Int
_ (Grammar
> { productions :: Grammar -> [Production]
productions = [Production]
p
> , token_specs :: Grammar -> [(Int, String)]
token_specs = [(Int, String)]
t
> , terminals :: Grammar -> [Int]
terminals = [Int]
ts
> , non_terminals :: Grammar -> [Int]
non_terminals = [Int]
nts
> , starts :: Grammar -> [(String, Int, Int, Bool)]
starts = [(String, Int, Int, Bool)]
sts
> , types :: Grammar -> Array Int (Maybe String)
types = Array Int (Maybe String)
tys
> , token_names :: Grammar -> Array Int String
token_names = Array Int String
e
> , first_nonterm :: Grammar -> Int
first_nonterm = Int
fnt
> , first_term :: Grammar -> Int
first_term = Int
ft
> , eof_term :: Grammar -> Int
eof_term = Int
eof
> })
> = String -> ShowS
showString String
"productions = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Production] -> ShowS
forall a. Show a => a -> ShowS
shows [Production]
p
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\ntoken_specs = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Int, String)] -> ShowS
forall a. Show a => a -> ShowS
shows [(Int, String)]
t
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\nterminals = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> ShowS
forall a. Show a => a -> ShowS
shows [Int]
ts
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\nnonterminals = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> ShowS
forall a. Show a => a -> ShowS
shows [Int]
nts
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\nstarts = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(String, Int, Int, Bool)] -> ShowS
forall a. Show a => a -> ShowS
shows [(String, Int, Int, Bool)]
sts
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\ntypes = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array Int (Maybe String) -> ShowS
forall a. Show a => a -> ShowS
shows Array Int (Maybe String)
tys
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\ntoken_names = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array Int String -> ShowS
forall a. Show a => a -> ShowS
shows Array Int String
e
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\nfirst_nonterm = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Show a => a -> ShowS
shows Int
fnt
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\nfirst_term = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Show a => a -> ShowS
shows Int
ft
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\neof = " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Show a => a -> ShowS
shows Int
eof
> ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
"\n"
> data Assoc = LeftAssoc | RightAssoc | None
> deriving Int -> Assoc -> ShowS
[Assoc] -> ShowS
Assoc -> String
(Int -> Assoc -> ShowS)
-> (Assoc -> String) -> ([Assoc] -> ShowS) -> Show Assoc
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Assoc -> ShowS
showsPrec :: Int -> Assoc -> ShowS
$cshow :: Assoc -> String
show :: Assoc -> String
$cshowList :: [Assoc] -> ShowS
showList :: [Assoc] -> ShowS
Show
> data Priority = No | Prio Assoc Int | PrioLowest
> deriving Int -> Priority -> ShowS
[Priority] -> ShowS
Priority -> String
(Int -> Priority -> ShowS)
-> (Priority -> String) -> ([Priority] -> ShowS) -> Show Priority
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Priority -> ShowS
showsPrec :: Int -> Priority -> ShowS
$cshow :: Priority -> String
show :: Priority -> String
$cshowList :: [Priority] -> ShowS
showList :: [Priority] -> ShowS
Show
> instance Eq Priority where
> Priority
No == :: Priority -> Priority -> Bool
== Priority
No = Bool
True
> Prio Assoc
_ Int
i == Prio Assoc
_ Int
j = Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
j
> Priority
_ == Priority
_ = Bool
False
> data ErrorHandlerType
> = ErrorHandlerTypeDefault
> | ErrorHandlerTypeExpList
>
> data Pragmas
> = Pragmas {
> Pragmas -> String
token_type :: String,
> Pragmas -> Bool
imported_identity :: Bool,
> Pragmas -> (Bool, String, String, String, String)
monad :: (Bool,String,String,String,String),
> Pragmas -> Maybe Int
expect :: Maybe Int,
> Pragmas -> Maybe (String, String)
lexer :: Maybe (String,String),
> Pragmas -> Maybe String
error_handler :: Maybe String,
> Pragmas -> ErrorHandlerType
error_sig :: ErrorHandlerType
> }
All the tokens in the grammar are mapped onto integers, for speed.
The namespace is broken up as follows:
epsilon = 0
error = 1
dummy = 2
%start = 3..s
non-terminals = s..n
terminals = n..m
%eof = m
where n_nonterminals = n - 3 (including %starts)
n_terminals = 1 + (m-n) + 1 (including error and %eof)
These numbers are deeply magical, change at your own risk. Several
other places rely on these being arranged as they are, including
ProduceCode.lhs and the various HappyTemplates.
Unfortunately this means you can't tell whether a given token is a
terminal or non-terminal without knowing the boundaries of the
namespace, which are kept in the Grammar structure.
In hindsight, this was probably a bad idea.
In normal and GHC-based parsers, these numbers are also used in the
generated grammar itself, except that the error token is mapped to -1.
For array-based parsers, see the note in Tabular/LALR.lhs.
> startName, eofName, errorName, dummyName :: String
> startName :: String
startName = String
"%start"
> eofName :: String
eofName = String
"%eof"
> errorName :: String
errorName = String
"error"
> dummyName :: String
dummyName = String
"%dummy"
> firstStartTok, dummyTok, errorTok, epsilonTok :: Name
> firstStartTok :: Int
firstStartTok = Int
3
> dummyTok :: Int
dummyTok = Int
2
> errorTok :: Int
errorTok = Int
1
> epsilonTok :: Int
epsilonTok = Int
0
Replace $$ with an arbitrary string, being careful to avoid ".." and '.'.
> mapDollarDollar :: String -> Maybe (String -> String)
> mapDollarDollar :: String -> Maybe ShowS
mapDollarDollar String
code0 = String -> String -> Maybe ShowS
go String
code0 String
""
> where go :: String -> String -> Maybe ShowS
go String
code String
acc =
> case String
code of
> [] -> Maybe ShowS
forall a. Maybe a
Nothing
>
> Char
'"' :String
r -> case ReadS String
forall a. Read a => ReadS a
reads String
code :: [(String,String)] of
> [] -> String -> String -> Maybe ShowS
go String
r (Char
'"'Char -> ShowS
forall a. a -> [a] -> [a]
:String
acc)
> (String
s,String
r'):[(String, String)]
_ -> String -> String -> Maybe ShowS
go String
r' (ShowS
forall a. [a] -> [a]
reverse (ShowS
forall a. Show a => a -> String
show String
s) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
acc)
> Char
a:Char
'\'' :String
r | Char -> Bool
isAlphaNum Char
a -> String -> String -> Maybe ShowS
go String
r (Char
'\''Char -> ShowS
forall a. a -> [a] -> [a]
:Char
aChar -> ShowS
forall a. a -> [a] -> [a]
:String
acc)
> Char
'\'' :String
r -> case ReadS Char
forall a. Read a => ReadS a
reads String
code :: [(Char,String)] of
> [] -> String -> String -> Maybe ShowS
go String
r (Char
'\''Char -> ShowS
forall a. a -> [a] -> [a]
:String
acc)
> (Char
c,String
r'):[(Char, String)]
_ -> String -> String -> Maybe ShowS
go String
r' (ShowS
forall a. [a] -> [a]
reverse (Char -> String
forall a. Show a => a -> String
show Char
c) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
acc)
> Char
'\\':Char
'$':String
r -> String -> String -> Maybe ShowS
go String
r (Char
'$'Char -> ShowS
forall a. a -> [a] -> [a]
:String
acc)
> Char
'$':Char
'$':String
r -> ShowS -> Maybe ShowS
forall a. a -> Maybe a
Just (\String
repl -> ShowS
forall a. [a] -> [a]
reverse String
acc String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
repl String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
r)
> Char
c:String
r -> String -> String -> Maybe ShowS
go String
r (Char
cChar -> ShowS
forall a. a -> [a] -> [a]
:String
acc)