{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module BNFC.Backend.C.CFtoCPrinter (cf2CPrinter) where
import Prelude hiding ((<>))
import Data.Bifunctor ( second )
import Data.Char ( toLower )
import Data.Either ( lefts )
import Data.Foldable ( toList )
import Data.List ( nub )
import Data.Maybe ( isJust )
import BNFC.CF
import BNFC.PrettyPrint
import BNFC.Utils ( (+++), uniqOn, whenJust, unless, unlessNull )
import BNFC.Backend.Common
import BNFC.Backend.Common.NamedVariables
import BNFC.Backend.Common.StrUtils (renderCharOrString)
cf2CPrinter :: CF -> (String, String)
cf2CPrinter :: CF -> (String, String)
cf2CPrinter CF
cf = (CF -> [(Cat, [Rule])] -> String
mkHFile CF
cf [(Cat, [Rule])]
groups, CF -> [(Cat, [Rule])] -> String
mkCFile CF
cf [(Cat, [Rule])]
groups)
where
groups :: [(Cat, [Rule])]
groups = [(Cat, [Rule])] -> [(Cat, [Rule])]
fixCoercions ([(Cat, [Rule])] -> [(Cat, [Rule])])
-> [(Cat, [Rule])] -> [(Cat, [Rule])]
forall a b. (a -> b) -> a -> b
$ [(Cat, [Rule])] -> [(Cat, [Rule])]
forall {a}. [(a, [Rule])] -> [(a, [Rule])]
filterOutDefs ([(Cat, [Rule])] -> [(Cat, [Rule])])
-> [(Cat, [Rule])] -> [(Cat, [Rule])]
forall a b. (a -> b) -> a -> b
$ CF -> [(Cat, [Rule])]
ruleGroupsInternals CF
cf
filterOutDefs :: [(a, [Rule])] -> [(a, [Rule])]
filterOutDefs = ((a, [Rule]) -> (a, [Rule])) -> [(a, [Rule])] -> [(a, [Rule])]
forall a b. (a -> b) -> [a] -> [b]
map (((a, [Rule]) -> (a, [Rule])) -> [(a, [Rule])] -> [(a, [Rule])])
-> ((a, [Rule]) -> (a, [Rule])) -> [(a, [Rule])] -> [(a, [Rule])]
forall a b. (a -> b) -> a -> b
$ ([Rule] -> [Rule]) -> (a, [Rule]) -> (a, [Rule])
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (([Rule] -> [Rule]) -> (a, [Rule]) -> (a, [Rule]))
-> ([Rule] -> [Rule]) -> (a, [Rule]) -> (a, [Rule])
forall a b. (a -> b) -> a -> b
$ (Rule -> Bool) -> [Rule] -> [Rule]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Rule -> Bool) -> [Rule] -> [Rule])
-> (Rule -> Bool) -> [Rule] -> [Rule]
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> (Rule -> Bool) -> Rule -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RFun -> Bool
forall a. IsFun a => a -> Bool
isDefinedRule (RFun -> Bool) -> (Rule -> RFun) -> Rule -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rule -> RFun
forall function. Rul function -> function
funRule
mkHFile :: CF -> [(Cat,[Rule])] -> String
mkHFile :: CF -> [(Cat, [Rule])] -> String
mkHFile CF
cf [(Cat, [Rule])]
groups = [String] -> String
unlines
[
String
header,
(Cat -> String) -> [Cat] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Cat -> String
prPrints [Cat]
eps,
((Cat, [Rule]) -> String) -> [(Cat, [Rule])] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Cat, [Rule]) -> String
prPrintDataH [(Cat, [Rule])]
groups,
(Cat -> String) -> [Cat] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Cat -> String
prShows [Cat]
eps,
((Cat, [Rule]) -> String) -> [(Cat, [Rule])] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Cat, [Rule]) -> String
prShowDataH [(Cat, [Rule])]
groups,
String
footer
]
where
eps :: [Cat]
eps = [Cat] -> [Cat]
forall a. Eq a => [a] -> [a]
nub ([Cat] -> [Cat])
-> (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cat -> Cat) -> [Cat] -> [Cat]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> Cat
normCat ([Cat] -> [Cat])
-> (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Cat -> [Cat]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall a b. (a -> b) -> a -> b
$ CF -> NonEmpty Cat
forall f. CFG f -> NonEmpty Cat
allEntryPoints CF
cf
prPrints :: Cat -> String
prPrints Cat
s | Cat -> Cat
normCat Cat
s Cat -> Cat -> Bool
forall a. Eq a => a -> a -> Bool
== Cat
s = String
"char *print" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p);\n"
where
s' :: String
s' = Cat -> String
identCat Cat
s
prPrints Cat
_ = String
""
prShows :: Cat -> String
prShows Cat
s | Cat -> Cat
normCat Cat
s Cat -> Cat -> Bool
forall a. Eq a => a -> a -> Bool
== Cat
s = String
"char *show" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p);\n"
where
s' :: String
s' = Cat -> String
identCat Cat
s
prShows Cat
_ = String
""
header :: String
header = [String] -> String
unlines
[
String
"#ifndef PRINTER_HEADER",
String
"#define PRINTER_HEADER",
String
"",
String
"#include \"Absyn.h\"",
String
"",
String
"/* Certain applications may improve performance by changing the buffer size */",
String
"#define BUFFER_INITIAL 2048",
String
"/* You may wish to change _L_PAREN or _R_PAREN */",
String
"#define _L_PAREN '('",
String
"#define _R_PAREN ')'",
String
"",
String
"/* The following are simple heuristics for rendering terminals */",
String
"/* You may wish to change them */",
String
"void renderCC(Char c);",
String
"void renderCS(String s);",
String
"void indent(void);",
String
"void backup(void);",
String
"void onEmptyLine(void);",
String
"void removeTrailingSpaces(void);",
String
"void removeTrailingWhitespace(void);",
String
""
]
footer :: String
footer = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
[String
"void pp" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(String s, int i);" | String
t <- CF -> [String]
forall f. CFG f -> [String]
tokenNames CF
cf]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
[String
"void sh" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(String s);" | String
t <- CF -> [String]
forall f. CFG f -> [String]
tokenNames CF
cf]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
[
String
"void ppInteger(Integer n, int i);",
String
"void ppDouble(Double d, int i);",
String
"void ppChar(Char c, int i);",
String
"void ppString(String s, int i);",
String
"void ppIdent(String s, int i);",
String
"void shInteger(Integer n);",
String
"void shDouble(Double d);",
String
"void shChar(Char c);",
String
"void shString(String s);",
String
"void shIdent(String s);",
String
"void bufAppendS(const char *s);",
String
"void bufAppendC(const char c);",
String
"void bufReset(void);",
String
"void resizeBuffer(void);",
String
"",
String
"#endif"
]
prPrintDataH :: (Cat, [Rule]) -> String
prPrintDataH :: (Cat, [Rule]) -> String
prPrintDataH (Cat
cat, [Rule]
_) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"void pp", String
cl, String
"(", String
cl, String
" p, int i);\n"]
where
cl :: String
cl = Cat -> String
identCat (Cat -> Cat
normCat Cat
cat)
prShowDataH :: (Cat, [Rule]) -> String
prShowDataH :: (Cat, [Rule]) -> String
prShowDataH (Cat
cat, [Rule]
_) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String
"void sh", String
cl, String
"(", String
cl, String
" p);\n"]
where
cl :: String
cl = Cat -> String
identCat (Cat -> Cat
normCat Cat
cat)
mkCFile :: CF -> [(Cat,[Rule])] -> String
mkCFile :: CF -> [(Cat, [Rule])] -> String
mkCFile CF
cf [(Cat, [Rule])]
groups = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[
String
header,
String
prRender,
(Cat -> String) -> [Cat] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Cat -> String
prPrintFun [Cat]
eps,
(Cat -> String) -> [Cat] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Cat -> String
prShowFun [Cat]
eps,
((Cat, [Rule]) -> String) -> [(Cat, [Rule])] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Cat, [Rule]) -> String
prPrintData [(Cat, [Rule])]
groups,
String
printBasics,
String
printTokens,
((Cat, [Rule]) -> String) -> [(Cat, [Rule])] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Cat, [Rule]) -> String
prShowData [(Cat, [Rule])]
groups,
String
showBasics,
String
showTokens,
String
footer
]
where
eps :: [Cat]
eps = [Cat] -> [Cat]
forall a. Eq a => [a] -> [a]
nub ([Cat] -> [Cat])
-> (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Cat -> Cat) -> [Cat] -> [Cat]
forall a b. (a -> b) -> [a] -> [b]
map Cat -> Cat
normCat ([Cat] -> [Cat])
-> (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty Cat -> [Cat]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (NonEmpty Cat -> [Cat]) -> NonEmpty Cat -> [Cat]
forall a b. (a -> b) -> a -> b
$ CF -> NonEmpty Cat
forall f. CFG f -> NonEmpty Cat
allEntryPoints CF
cf
header :: String
header = [String] -> String
unlines
[
String
"/*** BNFC-Generated Pretty Printer and Abstract Syntax Viewer ***/",
String
"",
String
"#include <ctype.h> /* isspace */",
String
"#include <stdio.h>",
String
"#include <string.h>",
String
"#include <stdlib.h>",
String
"#include \"Printer.h\"",
String
"",
String
"#define INDENT_WIDTH 2",
String
"",
String
"int _n_;",
String
"char *buf_;",
String
"int cur_;",
String
"int buf_size;",
String
""
]
printBasics :: String
printBasics = [String] -> String
unlines
[
String
"void ppInteger(Integer n, int i)",
String
"{",
String
" char tmp[20];",
String
" sprintf(tmp, \"%d\", n);",
String
" renderS(tmp);",
String
"}",
String
"void ppDouble(Double d, int i)",
String
"{",
String
" char tmp[24];",
String
" sprintf(tmp, \"%.15g\", d);",
String
" renderS(tmp);",
String
"}",
String
"void ppChar(Char c, int i)",
String
"{",
String
" char tmp[4];",
String
" sprintf(tmp, \"'%c'\", c);",
String
" renderS(tmp);",
String
"}",
String
"void ppString(String s, int i)",
String
"{",
String
" bufAppendC('\\\"');",
String
" bufAppendS(s);",
String
" bufAppendC('\\\"');",
String
" bufAppendC(' ');",
String
"}",
String
"void ppIdent(String s, int i)",
String
"{",
String
" renderS(s);",
String
"}",
String
""
]
printTokens :: String
printTokens = [String] -> String
unlines
[[String] -> String
unlines [
String
"void pp" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(String s, int i)",
String
"{",
String
" renderS(s);",
String
"}",
String
""
] | String
t <- CF -> [String]
forall f. CFG f -> [String]
tokenNames CF
cf
]
showBasics :: String
showBasics = [String] -> String
unlines
[
String
"void shInteger(Integer i)",
String
"{",
String
" char tmp[20];",
String
" sprintf(tmp, \"%d\", i);",
String
" bufAppendS(tmp);",
String
"}",
String
"void shDouble(Double d)",
String
"{",
String
" char tmp[24];",
String
" sprintf(tmp, \"%.15g\", d);",
String
" bufAppendS(tmp);",
String
"}",
String
"void shChar(Char c)",
String
"{",
String
" bufAppendC('\\'');",
String
" bufAppendC(c);",
String
" bufAppendC('\\'');",
String
"}",
String
"void shString(String s)",
String
"{",
String
" bufAppendC('\\\"');",
String
" bufAppendS(s);",
String
" bufAppendC('\\\"');",
String
"}",
String
"void shIdent(String s)",
String
"{",
String
" bufAppendC('\\\"');",
String
" bufAppendS(s);",
String
" bufAppendC('\\\"');",
String
"}",
String
""
]
showTokens :: String
showTokens = [String] -> String
unlines
[[String] -> String
unlines [
String
"void sh" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(String s)",
String
"{",
String
" bufAppendC('\\\"');",
String
" bufAppendS(s);",
String
" bufAppendC('\\\"');",
String
"}",
String
""
] | String
t <- CF -> [String]
forall f. CFG f -> [String]
tokenNames CF
cf
]
footer :: String
footer = [String] -> String
unlines
[
String
"void bufAppendS(const char *s)",
String
"{",
String
" int len = strlen(s);",
String
" int n;",
String
" while (cur_ + len >= buf_size)",
String
" {",
String
" buf_size *= 2; /* Double the buffer size */",
String
" resizeBuffer();",
String
" }",
String
" for(n = 0; n < len; n++)",
String
" {",
String
" buf_[cur_ + n] = s[n];",
String
" }",
String
" cur_ += len;",
String
" buf_[cur_] = 0;",
String
"}",
String
"void bufAppendC(const char c)",
String
"{",
String
" if (cur_ + 1 >= buf_size)",
String
" {",
String
" buf_size *= 2; /* Double the buffer size */",
String
" resizeBuffer();",
String
" }",
String
" buf_[cur_] = c;",
String
" cur_++;",
String
" buf_[cur_] = 0;",
String
"}",
String
"void bufReset(void)",
String
"{",
String
" cur_ = 0;",
String
" buf_size = BUFFER_INITIAL;",
String
" resizeBuffer();",
String
" memset(buf_, 0, buf_size);",
String
"}",
String
"void resizeBuffer(void)",
String
"{",
String
" char *temp = (char *) malloc(buf_size);",
String
" if (!temp)",
String
" {",
String
" fprintf(stderr, \"Error: Out of memory while attempting to grow buffer!\\n\");",
String
" exit(1);",
String
" }",
String
" if (buf_)",
String
" {",
String
" strncpy(temp, buf_, buf_size); /* peteg: strlcpy is safer, but not POSIX/ISO C. */",
String
" free(buf_);",
String
" }",
String
" buf_ = temp;",
String
"}",
String
"char *buf_;",
String
"int cur_, buf_size;",
String
""
]
prPrintFun :: Cat -> String
prPrintFun :: Cat -> String
prPrintFun Cat
ep | Cat -> Cat
normCat Cat
ep Cat -> Cat -> Bool
forall a. Eq a => a -> a -> Bool
== Cat
ep = [String] -> String
unlines
[
String
"char *print" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ep' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ep' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p)",
String
"{",
String
" _n_ = 0;",
String
" bufReset();",
String
" pp" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ep' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(p, 0);",
String
" return buf_;",
String
"}"
]
where
ep' :: String
ep' = Cat -> String
identCat Cat
ep
prPrintFun Cat
_ = String
""
prPrintData :: (Cat, [Rule]) -> String
prPrintData :: (Cat, [Rule]) -> String
prPrintData (Cat
cat, [Rule]
rules)
| Cat -> Bool
isList Cat
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
"void pp" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"("String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
+++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", int i)"
, String
"{"
, String
" if (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
+++ String
"== 0)"
, String
" { /* nil */"
]
, [Doc] -> ([Doc] -> [String]) -> [String]
forall m a. Monoid m => [a] -> ([a] -> m) -> m
unlessNull (((Integer, Rule) -> Bool) -> [Doc]
swRules (Integer, Rule) -> Bool
forall a. IsFun a => a -> Bool
isNilFun) (([Doc] -> [String]) -> [String])
-> ([Doc] -> [String]) -> [String]
forall a b. (a -> b) -> a -> b
$ \ [Doc]
docs ->
[ Doc -> String
render (Doc -> String) -> Doc -> String
forall a b. (a -> b) -> a -> b
$ Int -> Doc -> Doc
nest Int
4 (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [Doc]
docs ]
, [ String
" }" ]
, [Doc] -> ([Doc] -> [String]) -> [String]
forall m a. Monoid m => [a] -> ([a] -> m) -> m
unlessNull (((Integer, Rule) -> Bool) -> [Doc]
swRules (Integer, Rule) -> Bool
forall a. IsFun a => a -> Bool
isOneFun) (([Doc] -> [String]) -> [String])
-> ([Doc] -> [String]) -> [String]
forall a b. (a -> b) -> a -> b
$ \ [Doc]
docs ->
[ String
" else if (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
pre String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_ == 0)"
, String
" { /* last */"
, Doc -> String
render (Doc -> String) -> Doc -> String
forall a b. (a -> b) -> a -> b
$ Int -> Doc -> Doc
nest Int
4 (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [Doc]
docs
, String
" }"
]
, [Doc] -> ([Doc] -> [String]) -> [String]
forall m a. Monoid m => [a] -> ([a] -> m) -> m
unlessNull (((Integer, Rule) -> Bool) -> [Doc]
swRules (Integer, Rule) -> Bool
forall a. IsFun a => a -> Bool
isConsFun) (([Doc] -> [String]) -> [String])
-> ([Doc] -> [String]) -> [String]
forall a b. (a -> b) -> a -> b
$ \ [Doc]
docs ->
[ String
" else"
, String
" { /* cons */"
, Doc -> String
render (Doc -> String) -> Doc -> String
forall a b. (a -> b) -> a -> b
$ Int -> Doc -> Doc
nest Int
4 (Doc -> Doc) -> Doc -> Doc
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
vcat [Doc]
docs
, String
" }"
]
, [ String
"}"
, String
""
]
]
| Bool
otherwise = [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
"void pp" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p, int _i_)"
, String
"{"
, String
" switch(p->kind)"
, String
" {"
]
, (Rule -> [String]) -> [Rule] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Rule -> [String]
prPrintRule [Rule]
rules
, [ String
" default:"
, String
" fprintf(stderr, \"Error: bad kind field when printing " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Cat -> String
catToStr Cat
cat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"!\\n\");"
, String
" exit(1);"
, String
" }"
, String
"}"
, String
""
]
]
where
cl :: String
cl = Cat -> String
identCat (Cat -> Cat
normCat Cat
cat)
vname :: String
vname = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
cl
pre :: String
pre = String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"->"
prules :: [(Integer, Rule)]
prules = [Rule] -> [(Integer, Rule)]
sortRulesByPrecedence [Rule]
rules
swRules :: ((Integer, Rule) -> Bool) -> [Doc]
swRules (Integer, Rule) -> Bool
f = Doc -> [(Integer, Doc)] -> [Doc]
switchByPrecedence Doc
"i" ([(Integer, Doc)] -> [Doc]) -> [(Integer, Doc)] -> [Doc]
forall a b. (a -> b) -> a -> b
$
((Integer, Rule) -> (Integer, Doc))
-> [(Integer, Rule)] -> [(Integer, Doc)]
forall a b. (a -> b) -> [a] -> [b]
map ((Rule -> Doc) -> (Integer, Rule) -> (Integer, Doc)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ((Rule -> Doc) -> (Integer, Rule) -> (Integer, Doc))
-> (Rule -> Doc) -> (Integer, Rule) -> (Integer, Doc)
forall a b. (a -> b) -> a -> b
$ [Doc] -> Doc
sep ([Doc] -> Doc) -> (Rule -> [Doc]) -> Rule -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text ([String] -> [Doc]) -> (Rule -> [String]) -> Rule -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Rule -> [String]
forall a. IsFun a => String -> Rul a -> [String]
prPrintRule_ String
pre) ([(Integer, Rule)] -> [(Integer, Doc)])
-> [(Integer, Rule)] -> [(Integer, Doc)]
forall a b. (a -> b) -> a -> b
$
((Integer, Rule) -> Integer)
-> [(Integer, Rule)] -> [(Integer, Rule)]
forall b a. Eq b => (a -> b) -> [a] -> [a]
uniqOn (Integer, Rule) -> Integer
forall a b. (a, b) -> a
fst ([(Integer, Rule)] -> [(Integer, Rule)])
-> [(Integer, Rule)] -> [(Integer, Rule)]
forall a b. (a -> b) -> a -> b
$ ((Integer, Rule) -> Bool) -> [(Integer, Rule)] -> [(Integer, Rule)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Integer, Rule) -> Bool
f [(Integer, Rule)]
prules
renderX :: String -> Doc
renderX :: String -> Doc
renderX String
sep' = Doc
"render" Doc -> Doc -> Doc
<> Char -> Doc
char Char
sc Doc -> Doc -> Doc
<> Doc -> Doc
parens (String -> Doc
text String
sep)
where (Char
sc, String
sep) = String -> (Char, String)
renderCharOrString String
sep'
prPrintRule :: Rule -> [String]
prPrintRule :: Rule -> [String]
prPrintRule r :: Rule
r@(Rule RFun
fun RCat
_ SentForm
_ InternalRule
_) = Bool -> [String] -> [String]
forall m. Monoid m => Bool -> m -> m
unless (RFun -> Bool
forall a. IsFun a => a -> Bool
isCoercion RFun
fun) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ [ String
" case is_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fnm String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":"
, String
" if (_i_ > " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
p String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") renderC(_L_PAREN);"
]
, (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ String -> Rule -> [String]
forall a. IsFun a => String -> Rul a -> [String]
prPrintRule_ String
pre Rule
r
, [ String
" if (_i_ > " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
p String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") renderC(_R_PAREN);"
, String
" break;"
, String
""
]
]
where
p :: Integer
p = Rule -> Integer
forall f. Rul f -> Integer
precRule Rule
r
fnm :: String
fnm = RFun -> String
forall a. IsFun a => a -> String
funName RFun
fun
pre :: String
pre = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ String
"p->u.", (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
fnm, String
"_." ]
prPrintRule_ :: IsFun a => String -> Rul a -> [String]
prPrintRule_ :: forall a. IsFun a => String -> Rul a -> [String]
prPrintRule_ String
pre (Rule a
_ RCat
_ SentForm
items InternalRule
_) = (Either (Cat, Doc) String -> String)
-> [Either (Cat, Doc) String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Either (Cat, Doc) String -> String
prPrintItem String
pre) ([Either (Cat, Doc) String] -> [String])
-> [Either (Cat, Doc) String] -> [String]
forall a b. (a -> b) -> a -> b
$ SentForm -> [Either (Cat, Doc) String]
forall a. [Either Cat a] -> [Either (Cat, Doc) a]
numVars SentForm
items
prPrintItem :: String -> Either (Cat, Doc) String -> String
prPrintItem :: String -> Either (Cat, Doc) String -> String
prPrintItem String
pre = \case
Right String
t -> Doc -> String
render (String -> Doc
renderX String
t) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
";"
Left (Cat
cat, Doc
nt) -> [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
"pp"
, String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Cat -> String
identCat (Cat -> String) -> Cat -> String
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
cat) String -> String
basicFunName (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ Cat -> Maybe String
maybeTokenCat Cat
cat
, String
"(", String
pre, Doc -> String
render Doc
nt, String
", ", Integer -> String
forall a. Show a => a -> String
show (Cat -> Integer
precCat Cat
cat), String
");"
]
prShowFun :: Cat -> String
prShowFun :: Cat -> String
prShowFun Cat
ep | Cat -> Cat
normCat Cat
ep Cat -> Cat -> Bool
forall a. Eq a => a -> a -> Bool
== Cat
ep = [String] -> String
unlines
[
String
"char *show" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ep' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ep' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p)",
String
"{",
String
" _n_ = 0;",
String
" bufReset();",
String
" sh" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ep' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(p);",
String
" return buf_;",
String
"}"
]
where
ep' :: String
ep' = Cat -> String
identCat Cat
ep
prShowFun Cat
_ = String
""
prShowData :: (Cat, [Rule]) -> String
prShowData :: (Cat, [Rule]) -> String
prShowData (Cat
cat, [Rule]
rules) = [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
if Cat -> Bool
isList Cat
cat
then
[
String
"void sh" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"("String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
+++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")",
String
"{",
String
" bufAppendC('[');",
String
" while(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
+++ String
"!= 0)",
String
" {",
String
" if (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"->" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_)",
String
" {",
String
visitMember,
String
" bufAppendS(\", \");",
String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
+++ String
"=" String -> String -> String
+++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"->" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_;",
String
" }",
String
" else",
String
" {",
String
visitMember,
String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" = 0;",
String
" }",
String
" }",
String
" bufAppendC(']');",
String
"}",
String
""
]
else
[
String
"void sh" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" p)",
String
"{",
String
" switch(p->kind)",
String
" {",
(Rule -> String) -> [Rule] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Rule -> String
prShowRule [Rule]
rules,
String
" default:",
String
" fprintf(stderr, \"Error: bad kind field when showing " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Cat -> String
catToStr Cat
cat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"!\\n\");",
String
" exit(1);",
String
" }",
String
"}\n"
]
where
cl :: String
cl = Cat -> String
identCat (Cat -> Cat
normCat Cat
cat)
ecl :: String
ecl = Cat -> String
identCat (Cat -> Cat
normCatOfList Cat
cat)
vname :: String
vname = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
cl
member :: String
member = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
ecl
visitMember :: String
visitMember = String
" sh" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ecl String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
vname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"->" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
member String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"_);"
prShowRule :: Rule -> String
prShowRule :: Rule -> String
prShowRule (Rule RFun
fun RCat
_ SentForm
cats InternalRule
_) | Bool -> Bool
not (RFun -> Bool
forall a. IsFun a => a -> Bool
isCoercion RFun
fun) = [String] -> String
unlines
[
String
" case is_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":",
String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
lparen,
String
" bufAppendS(\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\");\n",
String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
optspace,
String
cats',
String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
rparen,
String
" break;"
]
where
f :: String
f = RFun -> String
forall a. IsFun a => a -> String
funName RFun
fun
(String
optspace, String
lparen, String
rparen) = if SentForm -> Bool
forall {a} {b}. [Either a b] -> Bool
allTerms SentForm
cats
then (String
"",String
"",String
"")
else (String
" bufAppendC(' ');\n", String
" bufAppendC('(');\n",String
" bufAppendC(')');\n")
cats' :: String
cats' = if SentForm -> Bool
forall {a} {b}. [Either a b] -> Bool
allTerms SentForm
cats
then String
""
else [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> [String]
forall {a}. (Eq a, IsString a) => [a] -> [a]
insertSpaces (((Cat, Doc) -> String) -> [(Cat, Doc)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> (Cat, Doc) -> String
prShowCat String
f) ([Either (Cat, Doc) String] -> [(Cat, Doc)]
forall a b. [Either a b] -> [a]
lefts ([Either (Cat, Doc) String] -> [(Cat, Doc)])
-> [Either (Cat, Doc) String] -> [(Cat, Doc)]
forall a b. (a -> b) -> a -> b
$ SentForm -> [Either (Cat, Doc) String]
forall a. [Either Cat a] -> [Either (Cat, Doc) a]
numVars SentForm
cats)))
insertSpaces :: [a] -> [a]
insertSpaces [] = []
insertSpaces (a
x:[]) = [a
x]
insertSpaces (a
x:[a]
xs) = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
""
then [a] -> [a]
insertSpaces [a]
xs
else a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a
" bufAppendC(' ');\n" a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a] -> [a]
insertSpaces [a]
xs
allTerms :: [Either a b] -> Bool
allTerms [] = Bool
True
allTerms (Left a
_:[Either a b]
_) = Bool
False
allTerms (Either a b
_:[Either a b]
zs) = [Either a b] -> Bool
allTerms [Either a b]
zs
prShowRule Rule
_ = String
""
prShowCat :: Fun -> (Cat, Doc) -> String
prShowCat :: String -> (Cat, Doc) -> String
prShowCat String
fnm (Cat
cat, Doc
nt) = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ String
" sh"
, String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Cat -> String
identCat (Cat -> String) -> Cat -> String
forall a b. (a -> b) -> a -> b
$ Cat -> Cat
normCat Cat
cat) String -> String
basicFunName (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ Cat -> Maybe String
maybeTokenCat Cat
cat
, String
"(p->u."
, (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower String
fnm
, String
"_."
, Doc -> String
render Doc
nt
, String
");\n"
]
basicFunName :: TokenCat -> String
basicFunName :: String -> String
basicFunName String
k
| String
k String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
baseTokenCatNames = String
k
| Bool
otherwise = String
"Ident"
prRender :: String
prRender :: String
prRender = [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
"/* You may wish to change the renderC functions */",
String
"void renderC(Char c)",
String
"{",
String
" if (c == '{')",
String
" {",
String
" onEmptyLine();",
String
" bufAppendC(c);",
String
" _n_ = _n_ + INDENT_WIDTH;",
String
" bufAppendC('\\n');",
String
" indent();",
String
" }",
String
" else if (c == '(' || c == '[')",
String
" bufAppendC(c);",
String
" else if (c == ')' || c == ']')",
String
" {",
String
" removeTrailingWhitespace();",
String
" bufAppendC(c);",
String
" bufAppendC(' ');",
String
" }",
String
" else if (c == '}')",
String
" {",
String
" _n_ = _n_ - INDENT_WIDTH;",
String
" onEmptyLine();",
String
" bufAppendC(c);",
String
" bufAppendC('\\n\');",
String
" indent();",
String
" }",
String
" else if (c == ',')",
String
" {",
String
" removeTrailingWhitespace();",
String
" bufAppendC(c);",
String
" bufAppendC(' ');",
String
" }",
String
" else if (c == ';')",
String
" {",
String
" removeTrailingWhitespace();",
String
" bufAppendC(c);",
String
" bufAppendC('\\n');",
String
" indent();",
String
" }",
String
" else if (c == ' ') bufAppendC(c);",
String
" else if (c == 0) return;",
String
" else",
String
" {",
String
" bufAppendC(c);",
String
" bufAppendC(' ');",
String
" }",
String
"}",
String
"",
String
"int allIsSpace(String s)",
String
"{",
String
" char c;",
String
" while ((c = *s++))",
String
" if (! isspace(c)) return 0;",
String
" return 1;",
String
"}",
String
"",
String
"void renderS(String s)",
String
"{",
String
" if (*s) /* s[0] != '\\0', string s not empty */",
String
" {",
String
" if (allIsSpace(s)) {",
String
" backup();",
String
" bufAppendS(s);",
String
" } else {",
String
" bufAppendS(s);",
String
" bufAppendC(' ');",
String
" }",
String
" }",
String
"}",
String
"",
String
"void indent(void)",
String
"{",
String
" int n = _n_;",
String
" while (--n >= 0)",
String
" bufAppendC(' ');",
String
"}",
String
"",
String
"void backup(void)",
String
"{",
String
" if (cur_ && buf_[cur_ - 1] == ' ')",
String
" buf_[--cur_] = 0;",
String
"}",
String
""
]
, [ String
"void removeTrailingSpaces()"
, String
"{"
, String
" while (cur_ && buf_[cur_ - 1] == ' ') --cur_;"
, String
" buf_[cur_] = 0;"
, String
"}"
, String
""
, String
"void removeTrailingWhitespace()"
, String
"{"
, String
" while (cur_ && (buf_[cur_ - 1] == ' ' || buf_[cur_ - 1] == '\\n')) --cur_;"
, String
" buf_[cur_] = 0;"
, String
"}"
, String
""
, String
"void onEmptyLine()"
, String
"{"
, String
" removeTrailingSpaces();"
, String
" if (cur_ && buf_[cur_ - 1 ] != '\\n') bufAppendC('\\n');"
, String
" indent();"
, String
"}"
]
]