{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TupleSections #-}
module BNFC.Backend.C.CFtoBisonC
( cf2Bison
, resultName, typeName, varName
, specialToks, startSymbol
, unionBuiltinTokens
)
where
import Prelude hiding ((<>))
import Data.Char ( toLower, isUpper )
import Data.Foldable ( toList )
import Data.List ( intercalate, nub )
import qualified Data.Map as Map
import System.FilePath ( (<.>) )
import BNFC.CF
import BNFC.Backend.Common.NamedVariables hiding (varName)
import BNFC.Backend.C.CFtoFlexC (ParserMode(..), cParser, stlParser, parserHExt, parserName, parserPackage)
import BNFC.Backend.CPP.Naming
import BNFC.Backend.CPP.STL.STLUtils
import BNFC.Options (RecordPositions(..), InPackage)
import BNFC.PrettyPrint
import BNFC.Utils ((+++), table, applyWhen, for, unless, when, whenJust)
type Rules = [(NonTerminal,[(Pattern,Action)])]
type Pattern = String
type Action = String
type MetaVar = String
cf2Bison :: RecordPositions -> ParserMode -> CF -> SymMap -> String
cf2Bison :: RecordPositions -> ParserMode -> CF -> SymMap -> String
cf2Bison RecordPositions
rp ParserMode
mode CF
cf SymMap
env = [String] -> String
unlines
[ ParserMode -> CF -> String
header ParserMode
mode CF
cf
, Doc -> String
render (Doc -> String) -> Doc -> String
forall a b. (a -> b) -> a -> b
$ ParserMode -> [NonTerminal] -> Doc
union ParserMode
mode ([NonTerminal] -> Doc) -> [NonTerminal] -> Doc
forall a b. (a -> b) -> a -> b
$ [NonTerminal]
posCats [NonTerminal] -> [NonTerminal] -> [NonTerminal]
forall a. [a] -> [a] -> [a]
++ CF -> [NonTerminal]
forall f. CFG f -> [NonTerminal]
allParserCatsNorm CF
cf
, String
""
, ParserMode -> String
unionDependentCode ParserMode
mode
, [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String -> [[String]] -> [String]
table String
" " ([[String]] -> [String]) -> [[String]] -> [String]
forall a b. (a -> b) -> a -> b
$ [[[String]]] -> [[String]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [String
"%token", String
"_ERROR_" ] ]
, [String] -> SymMap -> [[String]]
tokens (((String, Reg) -> String) -> [(String, Reg)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Reg) -> String
forall a b. (a, b) -> a
fst ([(String, Reg)] -> [String]) -> [(String, Reg)] -> [String]
forall a b. (a -> b) -> a -> b
$ CF -> [(String, Reg)]
forall f. CFG f -> [(String, Reg)]
tokenPragmas CF
cf) SymMap
env
, CF -> [[String]]
specialToks CF
cf
]
, ParserMode -> CF -> String
declarations ParserMode
mode CF
cf
, CF -> String
startSymbol CF
cf
, String
""
, String
"%%"
, String
""
, Rules -> String
prRules (Rules -> String) -> Rules -> String
forall a b. (a -> b) -> a -> b
$ RecordPositions -> ParserMode -> CF -> SymMap -> Rules
rulesForBison RecordPositions
rp ParserMode
mode CF
cf SymMap
env
, String
"%%"
, String
""
, Maybe String -> String
nsStart Maybe String
inPackage
, ParserMode -> CF -> String
entryCode ParserMode
mode CF
cf
, Maybe String -> String
nsEnd Maybe String
inPackage
]
where
inPackage :: Maybe String
inPackage = ParserMode -> Maybe String
parserPackage ParserMode
mode
posCats :: [NonTerminal]
posCats
| ParserMode -> Bool
stlParser ParserMode
mode = (String -> NonTerminal) -> [String] -> [NonTerminal]
forall a b. (a -> b) -> [a] -> [b]
map String -> NonTerminal
TokenCat ([String] -> [NonTerminal]) -> [String] -> [NonTerminal]
forall a b. (a -> b) -> a -> b
$ CF -> [String]
positionCats CF
cf
| Bool
otherwise = []
positionCats :: CF -> [String]
positionCats :: CF -> [String]
positionCats CF
cf = [ RFun -> String
forall a. WithPosition a -> a
wpThing RFun
name | TokenReg RFun
name Bool
True Reg
_ <- CF -> [Pragma]
forall function. CFG function -> [Pragma]
cfgPragmas CF
cf ]
header :: ParserMode -> CF -> String
ParserMode
mode CF
cf = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ String
"/* Parser definition to be used with Bison. */"
, String
""
, String
"/* Generate header file for lexer. */"
, String
"%defines \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String
"Bison" String -> String -> String
<.> String
h) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
]
, Maybe String -> (String -> [String]) -> [String]
forall m a. Monoid m => Maybe a -> (a -> m) -> m
whenJust (ParserMode -> Maybe String
parserPackage ParserMode
mode) ((String -> [String]) -> [String])
-> (String -> [String]) -> [String]
forall a b. (a -> b) -> a -> b
$ \ String
ns ->
[ String
"%name-prefix = \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ns String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
, String
" /* From Bison 2.6: %define api.prefix {" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ns String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"} */"
]
, [ String
""
, String
"/* Reentrant parser */"
, String
"%pure_parser"
, String
" /* From Bison 2.3b (2008): %define api.pure full */"
, String
"%lex-param { yyscan_t scanner }"
, String
"%parse-param { yyscan_t scanner }"
, String
""
, [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"/* Turn on line/column tracking in the ", String
name, String
"lloc structure: */" ]
, String
"%locations"
, String
""
, String
"/* Argument to the parser to be filled with the parsed tree. */"
, String
"%parse-param { YYSTYPE *result }"
, String
""
, String
"%{"
, String
"/* Begin C preamble code */"
, String
""
]
, Bool -> [String] -> [String]
forall m. Monoid m => Bool -> m -> m
when (ParserMode -> Bool
stlParser ParserMode
mode)
[ String
"#include <algorithm> /* for std::reverse */"
]
, [ String
"#include <stdio.h>"
, String
"#include <stdlib.h>"
, String
"#include <string.h>"
, String
"#include \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (String
"Absyn" String -> String -> String
<.> String
h) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
, String
""
, String
"#define YYMAXDEPTH 10000000"
, String
""
, String
"/* The type yyscan_t is defined by flex, but we need it in the parser already. */"
, String
"#ifndef YY_TYPEDEF_YY_SCANNER_T"
, String
"#define YY_TYPEDEF_YY_SCANNER_T"
, String
"typedef void* yyscan_t;"
, String
"#endif"
, String
""
, String
"typedef struct yy_buffer_state *YY_BUFFER_STATE;"
, String
"extern YY_BUFFER_STATE " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_scan_string(const char *str, yyscan_t scanner);"
, String
"extern void " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_delete_buffer(YY_BUFFER_STATE buf, yyscan_t scanner);"
, String
""
, String
"extern void " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"lex_destroy(yyscan_t scanner);"
, String
"extern char* " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"get_text(yyscan_t scanner);"
, String
""
, String
"extern yyscan_t " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_initialize_lexer(FILE * inp);"
, String
""
]
, Bool -> [String] -> [String]
forall m. Monoid m => Bool -> m -> m
unless (ParserMode -> Bool
stlParser ParserMode
mode)
[ String
"/* List reversal functions. */"
, (NonTerminal -> String) -> [NonTerminal] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ParserMode -> NonTerminal -> String
reverseList ParserMode
mode) ([NonTerminal] -> String) -> [NonTerminal] -> String
forall a b. (a -> b) -> a -> b
$ (NonTerminal -> Bool) -> [NonTerminal] -> [NonTerminal]
forall a. (a -> Bool) -> [a] -> [a]
filter NonTerminal -> Bool
isList ([NonTerminal] -> [NonTerminal]) -> [NonTerminal] -> [NonTerminal]
forall a b. (a -> b) -> a -> b
$ CF -> [NonTerminal]
forall f. CFG f -> [NonTerminal]
allParserCatsNorm CF
cf
]
, [ String
"/* End C preamble code */"
, String
"%}"
]
]
where
h :: String
h = ParserMode -> String
parserHExt ParserMode
mode
name :: String
name = ParserMode -> String
parserName ParserMode
mode
unionDependentCode :: ParserMode -> String
unionDependentCode :: ParserMode -> String
unionDependentCode ParserMode
mode = [String] -> String
unlines
[ String
"%{"
, String -> String
errorHandler String
name
, String
"int yyparse(yyscan_t scanner, YYSTYPE *result);"
, String
""
, String
"extern int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, yyscan_t scanner);"
, String
"%}"
]
where
name :: String
name = ParserMode -> String
parserName ParserMode
mode
errorHandler :: String -> String
errorHandler :: String -> String
errorHandler String
name = [String] -> String
unlines
[ String
"void yyerror(YYLTYPE *loc, yyscan_t scanner, YYSTYPE *result, const char *msg)"
, String
"{"
, String
" fprintf(stderr, \"error: %d,%d: %s at %s\\n\","
, String
" loc->first_line, loc->first_column, msg, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"get_text(scanner));"
, String
"}"
]
entryCode :: ParserMode -> CF -> String
entryCode :: ParserMode -> CF -> String
entryCode ParserMode
mode CF
cf = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (NonTerminal -> String) -> [NonTerminal] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (ParserMode -> CF -> NonTerminal -> String
parseMethod ParserMode
mode CF
cf) [NonTerminal]
eps
where
eps :: [NonTerminal]
eps = NonEmpty NonTerminal -> [NonTerminal]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (CF -> NonEmpty NonTerminal
forall f. CFG f -> NonEmpty NonTerminal
allEntryPoints CF
cf)
parseMethod :: ParserMode -> CF -> Cat -> String
parseMethod :: ParserMode -> CF -> NonTerminal -> String
parseMethod ParserMode
mode CF
cf NonTerminal
cat = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ [String] -> String
unwords [ String
"/* Entrypoint: parse", String
dat, String
"from file. */" ]
, String
dat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
parser String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(FILE *inp)"
]
, Bool -> [String]
body Bool
False
, [ String
""
, [String] -> String
unwords [ String
"/* Entrypoint: parse", String
dat, String
"from string. */" ]
, String
dat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ps" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
parser String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(const char *str)"
]
, Bool -> [String]
body Bool
True
]
where
name :: String
name = ParserMode -> String
parserName ParserMode
mode
body :: Bool -> [String]
body Bool
stringParser = [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ String
"{"
, String
" YYSTYPE result;"
, String
" yyscan_t scanner = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_initialize_lexer(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
file String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
");"
, String
" if (!scanner) {"
, String
" fprintf(stderr, \"Failed to initialize lexer.\\n\");"
, String
" return 0;"
, String
" }"
]
, [ String
" YY_BUFFER_STATE buf = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_scan_string(str, scanner);" | Bool
stringParser ]
, [ String
" int error = yyparse(scanner, &result);" ]
, [ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_delete_buffer(buf, scanner);" | Bool
stringParser ]
, [ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"lex_destroy(scanner);"
, String
" if (error)"
, String
" { /* Failure */"
, String
" return 0;"
, String
" }"
, String
" else"
, String
" { /* Success */"
]
, [String]
revOpt
, [ String
" return" String -> String -> String
+++ String
res String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
";"
, String
" }"
, String
"}"
]
]
where
file :: String
file | Bool
stringParser = String
"0"
| Bool
otherwise = String
"inp"
stl :: Bool
stl = ParserMode -> Bool
stlParser ParserMode
mode
ncat :: NonTerminal
ncat = NonTerminal -> NonTerminal
normCat NonTerminal
cat
dat0 :: String
dat0 = NonTerminal -> String
identCat NonTerminal
ncat
dat :: String
dat = if ParserMode -> Bool
cParser ParserMode
mode then String
dat0 else String
dat0 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"*"
parser :: String
parser = NonTerminal -> String
identCat NonTerminal
cat
res0 :: String
res0 = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"result.", NonTerminal -> String
varName NonTerminal
ncat ]
isReversible :: Bool
isReversible = NonTerminal
cat NonTerminal -> [NonTerminal] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` CF -> [NonTerminal]
forall f. CFG f -> [NonTerminal]
cfgReversibleCats CF
cf
res :: String
res
| Bool -> Bool
not Bool
stl, Bool
isReversible
= String
"reverse" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dat0 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
res0 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
| Bool
otherwise = String
res0
revOpt :: [String]
revOpt = Bool -> [String] -> [String]
forall m. Monoid m => Bool -> m -> m
when (Bool
stl Bool -> Bool -> Bool
&& NonTerminal -> Bool
isList NonTerminal
cat Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
isReversible)
[ String
"std::reverse(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
res String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"->begin(), " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
res String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"->end());" ]
reverseList :: ParserMode -> Cat -> String
reverseList :: ParserMode -> NonTerminal -> String
reverseList ParserMode
mode NonTerminal
c0 = [String] -> String
unlines
[ String
c' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" reverse" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c' String -> String -> String
+++ String
"l)"
, String
"{"
, String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c' String -> String -> String
+++String
"prev = 0;"
, String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c' String -> String -> String
+++String
"tmp = 0;"
, String
" while (l)"
, String
" {"
, String
" tmp = l->" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
v String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
";"
, String
" l->" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
v String -> String -> String
+++ String
"= prev;"
, String
" prev = l;"
, String
" l = tmp;"
, String
" }"
, String
" return prev;"
, String
"}"
]
where
c :: String
c = NonTerminal -> String
identCat (NonTerminal -> NonTerminal
normCat NonTerminal
c0)
c' :: String
c' = String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
star
v :: String
v = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_"
star :: String
star = if ParserMode -> Bool
cParser ParserMode
mode then String
"" else String
"*"
union :: ParserMode -> [Cat] -> Doc
union :: ParserMode -> [NonTerminal] -> Doc
union ParserMode
mode [NonTerminal]
cats = [Doc] -> Doc
vcat
[ Doc
"%union"
, Int -> [Doc] -> Doc
codeblock Int
2 ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ (String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text [String]
unionBuiltinTokens [Doc] -> [Doc] -> [Doc]
forall a. [a] -> [a] -> [a]
++ (NonTerminal -> Doc) -> [NonTerminal] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map NonTerminal -> Doc
mkPointer [NonTerminal]
normCats
]
where
normCats :: [NonTerminal]
normCats = [NonTerminal] -> [NonTerminal]
forall a. Eq a => [a] -> [a]
nub ((NonTerminal -> NonTerminal) -> [NonTerminal] -> [NonTerminal]
forall a b. (a -> b) -> [a] -> [b]
map NonTerminal -> NonTerminal
normCat [NonTerminal]
cats)
mkPointer :: NonTerminal -> Doc
mkPointer NonTerminal
s = Doc
scope Doc -> Doc -> Doc
<> String -> Doc
text (NonTerminal -> String
identCat NonTerminal
s) Doc -> Doc -> Doc
<> Doc
star Doc -> Doc -> Doc
<+> String -> Doc
text (NonTerminal -> String
varName NonTerminal
s) Doc -> Doc -> Doc
<> Doc
";"
scope :: Doc
scope = String -> Doc
text (String -> Doc) -> String -> Doc
forall a b. (a -> b) -> a -> b
$ Maybe String -> String
nsScope (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ ParserMode -> Maybe String
parserPackage ParserMode
mode
star :: Doc
star = if ParserMode -> Bool
cParser ParserMode
mode then Doc
empty else String -> Doc
text String
"*"
unionBuiltinTokens :: [String]
unionBuiltinTokens :: [String]
unionBuiltinTokens =
[ String
"int _int;"
, String
"char _char;"
, String
"double _double;"
, String
"char* _string;"
]
declarations :: ParserMode -> CF -> String
declarations :: ParserMode -> CF -> String
declarations ParserMode
mode CF
cf = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (NonTerminal -> String) -> [NonTerminal] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map NonTerminal -> String
typeNT ([NonTerminal] -> [String]) -> [NonTerminal] -> [String]
forall a b. (a -> b) -> a -> b
$
[NonTerminal]
posCats [NonTerminal] -> [NonTerminal] -> [NonTerminal]
forall a. [a] -> [a] -> [a]
++
(NonTerminal -> Bool) -> [NonTerminal] -> [NonTerminal]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (NonTerminal -> Bool) -> NonTerminal -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Rule] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([Rule] -> Bool) -> (NonTerminal -> [Rule]) -> NonTerminal -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CF -> NonTerminal -> [Rule]
rulesForCat CF
cf) (CF -> [NonTerminal]
forall f. CFG f -> [NonTerminal]
allParserCats CF
cf)
where
typeNT :: NonTerminal -> String
typeNT NonTerminal
nt = String
"%type <" String -> String -> String
forall a. [a] -> [a] -> [a]
++ NonTerminal -> String
varName NonTerminal
nt String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ NonTerminal -> String
identCat NonTerminal
nt
posCats :: [NonTerminal]
posCats
| ParserMode -> Bool
stlParser ParserMode
mode = (String -> NonTerminal) -> [String] -> [NonTerminal]
forall a b. (a -> b) -> [a] -> [b]
map String -> NonTerminal
TokenCat ([String] -> [NonTerminal]) -> [String] -> [NonTerminal]
forall a b. (a -> b) -> a -> b
$ CF -> [String]
positionCats CF
cf
| Bool
otherwise = []
tokens :: [UserDef] -> SymMap -> [[String]]
tokens :: [String] -> SymMap -> [[String]]
tokens [String]
user SymMap
env = ((SymKey, String) -> [String]) -> [(SymKey, String)] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map (SymKey, String) -> [String]
declTok ([(SymKey, String)] -> [[String]])
-> [(SymKey, String)] -> [[String]]
forall a b. (a -> b) -> a -> b
$ SymMap -> [(SymKey, String)]
forall k a. Map k a -> [(k, a)]
Map.toList SymMap
env
where
declTok :: (SymKey, String) -> [String]
declTok (Keyword String
s, String
r) = String -> String -> String -> [String]
tok String
"" String
s String
r
declTok (Tokentype String
s, String
r) = String -> String -> String -> [String]
tok (if String
s String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
user then String
"<_string>" else String
"") String
s String
r
tok :: String -> String -> String -> [String]
tok String
t String
s String
r = [ String
"%token" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t, String
r, String
" /* " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
cStringEscape String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" */" ]
cStringEscape :: String -> String
cStringEscape :: String -> String
cStringEscape = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
escChar
where
escChar :: Char -> String
escChar Char
c
| Char
c Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (String
"\"\\" :: String) = Char
'\\'Char -> String -> String
forall a. a -> [a] -> [a]
:[Char
c]
| Bool
otherwise = [Char
c]
specialToks :: CF -> [[String]]
specialToks :: CF -> [[String]]
specialToks CF
cf = [[[String]]] -> [[String]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String -> [String] -> [[String]]
forall {a}. String -> a -> [a]
ifC String
catString [ String
"%token<_string>", String
"_STRING_" ]
, String -> [String] -> [[String]]
forall {a}. String -> a -> [a]
ifC String
catChar [ String
"%token<_char> ", String
"_CHAR_" ]
, String -> [String] -> [[String]]
forall {a}. String -> a -> [a]
ifC String
catInteger [ String
"%token<_int> ", String
"_INTEGER_" ]
, String -> [String] -> [[String]]
forall {a}. String -> a -> [a]
ifC String
catDouble [ String
"%token<_double>", String
"_DOUBLE_" ]
, String -> [String] -> [[String]]
forall {a}. String -> a -> [a]
ifC String
catIdent [ String
"%token<_string>", String
"_IDENT_" ]
]
where
ifC :: String -> a -> [a]
ifC String
cat a
s = if CF -> NonTerminal -> Bool
forall f. CFG f -> NonTerminal -> Bool
isUsedCat CF
cf (String -> NonTerminal
TokenCat String
cat) then [a
s] else []
startSymbol :: CF -> String
startSymbol :: CF -> String
startSymbol CF
cf = String
"%start" String -> String -> String
+++ NonTerminal -> String
identCat (CF -> NonTerminal
firstEntry CF
cf)
rulesForBison :: RecordPositions -> ParserMode -> CF -> SymMap -> Rules
rulesForBison :: RecordPositions -> ParserMode -> CF -> SymMap -> Rules
rulesForBison RecordPositions
rp ParserMode
mode CF
cf SymMap
env = ((NonTerminal, [Rule]) -> (NonTerminal, [(String, String)]))
-> [(NonTerminal, [Rule])] -> Rules
forall a b. (a -> b) -> [a] -> [b]
map (NonTerminal, [Rule]) -> (NonTerminal, [(String, String)])
mkOne (CF -> [(NonTerminal, [Rule])]
ruleGroups CF
cf) Rules -> Rules -> Rules
forall a. [a] -> [a] -> [a]
++ Rules
posRules
where
mkOne :: (NonTerminal, [Rule]) -> (NonTerminal, [(String, String)])
mkOne (NonTerminal
cat,[Rule]
rules) = RecordPositions
-> ParserMode
-> CF
-> SymMap
-> [Rule]
-> NonTerminal
-> (NonTerminal, [(String, String)])
constructRule RecordPositions
rp ParserMode
mode CF
cf SymMap
env [Rule]
rules NonTerminal
cat
posRules :: Rules
posRules :: Rules
posRules
| CppParser Maybe String
inPackage String
_ <- ParserMode
mode = [String] -> (String -> (NonTerminal, [(String, String)])) -> Rules
forall a b. [a] -> (a -> b) -> [b]
for (CF -> [String]
positionCats CF
cf) ((String -> (NonTerminal, [(String, String)])) -> Rules)
-> (String -> (NonTerminal, [(String, String)])) -> Rules
forall a b. (a -> b) -> a -> b
$ \ String
n -> (String -> NonTerminal
TokenCat String
n,
[( String -> SymKey -> SymMap -> String
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault String
n (String -> SymKey
Tokentype String
n) SymMap
env
, CF -> NonTerminal -> String -> String
addResult CF
cf (String -> NonTerminal
TokenCat String
n) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
"$$ = new ", Maybe String -> String
nsScope Maybe String
inPackage, String
n, String
"($1, @$.first_line);" ]
)])
| Bool
otherwise = []
constructRule
:: RecordPositions -> ParserMode -> CF -> SymMap
-> [Rule]
-> NonTerminal
-> (NonTerminal,[(Pattern,Action)])
constructRule :: RecordPositions
-> ParserMode
-> CF
-> SymMap
-> [Rule]
-> NonTerminal
-> (NonTerminal, [(String, String)])
constructRule RecordPositions
rp ParserMode
mode CF
cf SymMap
env [Rule]
rules NonTerminal
nt = (NonTerminal
nt,) ([(String, String)] -> (NonTerminal, [(String, String)]))
-> [(String, String)] -> (NonTerminal, [(String, String)])
forall a b. (a -> b) -> a -> b
$
[ (String
p,) (String -> (String, String)) -> String -> (String, String)
forall a b. (a -> b) -> a -> b
$ CF -> NonTerminal -> String -> String
addResult CF
cf NonTerminal
nt (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ RecordPositions
-> ParserMode
-> String
-> RFun
-> Bool
-> [(String, Bool)]
-> String
forall a.
IsFun a =>
RecordPositions
-> ParserMode -> String -> a -> Bool -> [(String, Bool)] -> String
generateAction RecordPositions
rp ParserMode
mode (NonTerminal -> String
identCat (NonTerminal -> NonTerminal
normCat NonTerminal
nt)) (Rule -> RFun
forall function. Rul function -> function
funRule Rule
r) Bool
b [(String, Bool)]
m
| Rule
r0 <- [Rule]
rules
, let (Bool
b,Rule
r) = if RFun -> Bool
forall a. IsFun a => a -> Bool
isConsFun (Rule -> RFun
forall function. Rul function -> function
funRule Rule
r0) Bool -> Bool -> Bool
&& Rule -> NonTerminal
forall fun. Rul fun -> NonTerminal
valCat Rule
r0 NonTerminal -> [NonTerminal] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` CF -> [NonTerminal]
forall f. CFG f -> [NonTerminal]
cfgReversibleCats CF
cf
then (Bool
True, Rule -> Rule
forall f. Rul f -> Rul f
revSepListRule Rule
r0)
else (Bool
False, Rule
r0)
, let (String
p,[(String, Bool)]
m) = ParserMode -> CF -> SymMap -> Rule -> (String, [(String, Bool)])
generatePatterns ParserMode
mode CF
cf SymMap
env Rule
r
]
addResult :: CF -> NonTerminal -> Action -> Action
addResult :: CF -> NonTerminal -> String -> String
addResult CF
cf NonTerminal
nt String
a =
if NonTerminal
nt NonTerminal -> [NonTerminal] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` NonEmpty NonTerminal -> [NonTerminal]
forall a. NonEmpty a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (CF -> NonEmpty NonTerminal
forall f. CFG f -> NonEmpty NonTerminal
allEntryPoints CF
cf)
then [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
a, String
" result->", NonTerminal -> String
varName (NonTerminal -> NonTerminal
normCat NonTerminal
nt), String
" = $$;" ]
else String
a
generateAction :: IsFun a
=> RecordPositions
-> ParserMode
-> String
-> a
-> Bool
-> [(MetaVar, Bool)]
-> Action
generateAction :: forall a.
IsFun a =>
RecordPositions
-> ParserMode -> String -> a -> Bool -> [(String, Bool)] -> String
generateAction RecordPositions
rp = \case
CppParser Maybe String
ns String
_ -> RecordPositions
-> Maybe String
-> String
-> a
-> Bool
-> [(String, Bool)]
-> String
forall a.
IsFun a =>
RecordPositions
-> Maybe String
-> String
-> a
-> Bool
-> [(String, Bool)]
-> String
generateActionSTL RecordPositions
rp Maybe String
ns
CParser Bool
b String
_ -> \ String
nt a
f Bool
r -> RecordPositions
-> Bool -> String -> a -> Bool -> [String] -> String
forall a.
IsFun a =>
RecordPositions
-> Bool -> String -> a -> Bool -> [String] -> String
generateActionC RecordPositions
rp (Bool -> Bool
not Bool
b) String
nt a
f Bool
r ([String] -> String)
-> ([(String, Bool)] -> [String]) -> [(String, Bool)] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((String, Bool) -> String) -> [(String, Bool)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Bool) -> String
forall a b. (a, b) -> a
fst
generateActionC :: IsFun a => RecordPositions -> Bool -> String -> a -> Bool -> [MetaVar] -> Action
generateActionC :: forall a.
IsFun a =>
RecordPositions
-> Bool -> String -> a -> Bool -> [String] -> String
generateActionC RecordPositions
rp Bool
cParser String
nt a
f Bool
b [String]
ms
| a -> Bool
forall a. IsFun a => a -> Bool
isCoercion a
f = String
"$$ = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
ms String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
";" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
loc
| a -> Bool
forall a. IsFun a => a -> Bool
isNilFun a
f = String
"$$ = 0;"
| a -> Bool
forall a. IsFun a => a -> Bool
isOneFun a
f = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String -> String
new String
nt, String
"(", String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
ms', String
", 0);"]
| a -> Bool
forall a. IsFun a => a -> Bool
isConsFun a
f = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String -> String
new String
nt, String
"(", String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
ms', String
");"]
| Bool
otherwise = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String -> String
new (a -> String
forall a. IsFun a => a -> String
funName a
f), String
"(", String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
ms', String
");", String
loc]
where
ms' :: [String]
ms' = if Bool
b then [String] -> [String]
forall a. [a] -> [a]
reverse [String]
ms else [String]
ms
loc :: String
loc | RecordPositions
RecordPositions <- RecordPositions
rp
= String
" $$->line_number = @$.first_line; $$->char_number = @$.first_column;"
| Bool
otherwise
= String
""
new :: String -> String
new :: String -> String
new | Bool
cParser = (String
"make_" String -> String -> String
forall a. [a] -> [a] -> [a]
++)
| Bool
otherwise = \ String
s -> if Char -> Bool
isUpper (String -> Char
forall a. HasCallStack => [a] -> a
head String
s) then String
"new " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s else String -> String
sanitizeCpp String
s
generateActionSTL :: IsFun a => RecordPositions -> InPackage -> String -> a -> Bool -> [(MetaVar,Bool)] -> Action
generateActionSTL :: forall a.
IsFun a =>
RecordPositions
-> Maybe String
-> String
-> a
-> Bool
-> [(String, Bool)]
-> String
generateActionSTL RecordPositions
rp Maybe String
inPackage String
nt a
f Bool
b [(String, Bool)]
mbs = String
reverses String -> String -> String
forall a. [a] -> [a] -> [a]
++
if | a -> Bool
forall a. IsFun a => a -> Bool
isCoercion a
f -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", [String] -> String
unwords [String]
ms, String
";", String
loc]
| a -> Bool
forall a. IsFun a => a -> Bool
isNilFun a
f -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String
"new ", String
scope, String
nt, String
"();"]
| a -> Bool
forall a. IsFun a => a -> Bool
isOneFun a
f -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String
"new ", String
scope, String
nt, String
"(); $$->push_back(", [String] -> String
forall a. HasCallStack => [a] -> a
head [String]
ms, String
");"]
| a -> Bool
forall a. IsFun a => a -> Bool
isConsFun a
f -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
lst, String
"->push_back(", String
el, String
"); $$ = ", String
lst, String
";"]
| a -> Bool
forall a. IsFun a => a -> Bool
isDefinedRule a
f -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String
scope, String -> String
sanitizeCpp (a -> String
forall a. IsFun a => a -> String
funName a
f), String
"(", String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
ms, String
");" ]
| Bool
otherwise -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"$$ = ", String
"new ", String
scope, a -> String
forall a. IsFun a => a -> String
funName a
f, String
"(", String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
ms, String
");", String
loc]
where
ms :: [String]
ms = ((String, Bool) -> String) -> [(String, Bool)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, Bool) -> String
forall a b. (a, b) -> a
fst [(String, Bool)]
mbs
[String
el, String
lst] = Bool -> ([String] -> [String]) -> [String] -> [String]
forall a. Bool -> (a -> a) -> a -> a
applyWhen Bool
b [String] -> [String]
forall a. [a] -> [a]
reverse [String]
ms
loc :: String
loc | RecordPositions
RecordPositions <- RecordPositions
rp
= String
" $$->line_number = @$.first_line; $$->char_number = @$.first_column;"
| Bool
otherwise
= String
""
reverses :: String
reverses = [String] -> String
unwords [String
"std::reverse(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
m String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"->begin(),"String -> String -> String
forall a. [a] -> [a] -> [a]
++String
mString -> String -> String
forall a. [a] -> [a] -> [a]
++String
"->end()) ;" | (String
m, Bool
True) <- [(String, Bool)]
mbs]
scope :: String
scope = Maybe String -> String
nsScope Maybe String
inPackage
generatePatterns :: ParserMode -> CF -> SymMap -> Rule -> (Pattern,[(MetaVar,Bool)])
generatePatterns :: ParserMode -> CF -> SymMap -> Rule -> (String, [(String, Bool)])
generatePatterns ParserMode
mode CF
cf SymMap
env Rule
r = case Rule -> SentForm
forall function. Rul function -> SentForm
rhsRule Rule
r of
[] -> (String
"/* empty */",[])
SentForm
its -> ([String] -> String
unwords ((Either NonTerminal String -> String) -> SentForm -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Either NonTerminal String -> String
mkIt SentForm
its), SentForm -> [(String, Bool)]
forall {b}. [Either NonTerminal b] -> [(String, Bool)]
metas SentForm
its)
where
stl :: Bool
stl = ParserMode -> Bool
stlParser ParserMode
mode
mkIt :: Either NonTerminal String -> String
mkIt = \case
Left (TokenCat String
s)
| Bool
stl Bool -> Bool -> Bool
&& CF -> String -> Bool
forall f. CFG f -> String -> Bool
isPositionCat CF
cf String
s
-> String -> String
typeName String
s
| Bool
otherwise -> String -> SymKey -> SymMap -> String
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault (String -> String
typeName String
s) (String -> SymKey
Tokentype String
s) SymMap
env
Left NonTerminal
c -> NonTerminal -> String
identCat NonTerminal
c
Right String
s -> String -> SymKey -> SymMap -> String
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault String
s (String -> SymKey
Keyword String
s) SymMap
env
metas :: [Either NonTerminal b] -> [(String, Bool)]
metas [Either NonTerminal b]
its = [(NonTerminal -> String -> String
revIf NonTerminal
c (Char
'$'Char -> String -> String
forall a. a -> [a] -> [a]
: Int -> String
forall a. Show a => a -> String
show Int
i), NonTerminal -> Bool
revert NonTerminal
c) | (Int
i, Left NonTerminal
c) <- [Int] -> [Either NonTerminal b] -> [(Int, Either NonTerminal b)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1 :: Int ..] [Either NonTerminal b]
its]
revIf :: NonTerminal -> String -> String
revIf NonTerminal
c String
m = if Bool -> Bool
not Bool
stl Bool -> Bool -> Bool
&& Bool
isntCons Bool -> Bool -> Bool
&& NonTerminal -> [NonTerminal] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem NonTerminal
c [NonTerminal]
revs
then String
"reverse" String -> String -> String
forall a. [a] -> [a] -> [a]
++ NonTerminal -> String
identCat (NonTerminal -> NonTerminal
normCat NonTerminal
c) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
m String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"
else String
m
revert :: NonTerminal -> Bool
revert NonTerminal
c = Bool
isntCons Bool -> Bool -> Bool
&& NonTerminal -> Bool
isList NonTerminal
c Bool -> Bool -> Bool
&& NonTerminal -> [NonTerminal] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem NonTerminal
c [NonTerminal]
revs
revs :: [NonTerminal]
revs = CF -> [NonTerminal]
forall f. CFG f -> [NonTerminal]
cfgReversibleCats CF
cf
isntCons :: Bool
isntCons = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ RFun -> Bool
forall a. IsFun a => a -> Bool
isConsFun (RFun -> Bool) -> RFun -> Bool
forall a b. (a -> b) -> a -> b
$ Rule -> RFun
forall function. Rul function -> function
funRule Rule
r
prRules :: Rules -> String
prRules :: Rules -> String
prRules [] = []
prRules ((NonTerminal
_, []):Rules
rs) = Rules -> String
prRules Rules
rs
prRules ((NonTerminal
nt, (String
p,String
a) : [(String, String)]
ls):Rules
rs) =
[String] -> String
unwords [String
nt', String
":" , String
p, String
"{", String
a, String
"}", Char
'\n' Char -> String -> String
forall a. a -> [a] -> [a]
: [(String, String)] -> String
pr [(String, String)]
ls] String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
";\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Rules -> String
prRules Rules
rs
where
nt' :: String
nt' = NonTerminal -> String
identCat NonTerminal
nt
pr :: [(String, String)] -> String
pr [] = []
pr ((String
p,String
a):[(String, String)]
ls) = [String] -> String
unlines [[String] -> String
unwords [String
" |", String
p, String
"{", String
a , String
"}"]] String -> String -> String
forall a. [a] -> [a] -> [a]
++ [(String, String)] -> String
pr [(String, String)]
ls
resultName :: String -> String
resultName :: String -> String
resultName String
s = String
"YY_RESULT_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_"
varName :: Cat -> String
varName :: NonTerminal -> String
varName = \case
TokenCat String
s -> String
"_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
s
NonTerminal
c -> (String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_") (String -> String)
-> (NonTerminal -> String) -> NonTerminal -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower (String -> String)
-> (NonTerminal -> String) -> NonTerminal -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonTerminal -> String
identCat (NonTerminal -> String)
-> (NonTerminal -> NonTerminal) -> NonTerminal -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonTerminal -> NonTerminal
normCat (NonTerminal -> String) -> NonTerminal -> String
forall a b. (a -> b) -> a -> b
$ NonTerminal
c
typeName :: String -> String
typeName :: String -> String
typeName String
"Ident" = String
"_IDENT_"
typeName String
"String" = String
"_STRING_"
typeName String
"Char" = String
"_CHAR_"
typeName String
"Integer" = String
"_INTEGER_"
typeName String
"Double" = String
"_DOUBLE_"
typeName String
x = String
x