module PP.Grammars.LexicalHelper
(
LexicalRule(..)
, LexicalDefinitionList(..)
, LexicalDefinition(..)
, lexicalString
) where
import Control.Applicative ((<$>), (<*>))
import Data.Text (pack, strip, unpack)
import PP.Grammar
import qualified PP.Rule as R
import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Language (emptyDef)
import qualified Text.ParserCombinators.Parsec.Token as Token
data LexicalRule = LexicalRule String LexicalDefinitionList
deriving (Show, Eq)
newtype LexicalDefinitionList = LexicalDefinitionList [LexicalDefinition]
deriving (Show, Eq)
data LexicalDefinition
= LexicalRegEx String
| LexicalString String
| LexicalIdentifier String
deriving (Show, Eq)
lexicalString :: String -> String -> LexicalRule
lexicalString n s = LexicalRule n $ LexicalDefinitionList [LexicalString s]
lexer = Token.makeTokenParser def
where
def = emptyDef {
Token.commentStart = "(*"
, Token.commentEnd = "*)"
, Token.commentLine = ""
, Token.nestedComments = False
, Token.identStart = letter
, Token.identLetter = alphaNum <|> oneOf "_- "
, Token.reservedNames = []
, Token.reservedOpNames = ["%=", ";", ","]
, Token.caseSensitive = True
}
identifier = Token.identifier lexer
reservedOp = Token.reservedOp lexer
stringLiteral = Token.stringLiteral lexer
whiteSpace = Token.whiteSpace lexer
lexicalRule :: Parser LexicalRule
lexicalRule = whiteSpace *>
(LexicalRule <$> (lexicalIdentifier <* reservedOp "%=")
<*> (lexicalDefinitionList <* reservedOp ";"))
<?> "lexical rule"
lexicalDefinitionList :: Parser LexicalDefinitionList
lexicalDefinitionList = LexicalDefinitionList <$> sepBy1 lexicalDefinition (reservedOp ",")
<?> "lexical definition list"
lexicalDefinition :: Parser LexicalDefinition
lexicalDefinition = LexicalRegEx <$> stringLiteral
<|> LexicalIdentifier <$> lexicalIdentifier
<?> "lexical definition"
lexicalIdentifier :: Parser String
lexicalIdentifier = (unpack . strip . pack) <$> identifier
<?> "lexical identifier"
instance InputGrammar LexicalRule where
parser = lexicalRule
stringify (LexicalRule li xs) = li ++ "%=" ++ stringify xs ++ ";"
rules (LexicalRule li xs) = R.uniformize [R.Rule li (rules xs ++ [R.Empty])]
instance InputGrammar LexicalDefinitionList where
parser = lexicalDefinitionList
stringify (LexicalDefinitionList []) = ""
stringify (LexicalDefinitionList [x]) = stringify x
stringify (LexicalDefinitionList (x:xs)) =
stringify x ++ "," ++ stringify (LexicalDefinitionList xs)
rules (LexicalDefinitionList xs) = [head (rules x) | x <- xs]
instance InputGrammar LexicalDefinition where
parser = lexicalDefinition
stringify (LexicalString x) = show x
stringify (LexicalRegEx x) = show x
stringify (LexicalIdentifier x) = x
rules (LexicalRegEx x) = [R.RegEx x]
rules (LexicalString x) = [R.RegExString x]
rules (LexicalIdentifier x) = [R.NonTerm x]