Merge pull request #4820 from joshuawarner32/remove-parser-generator

Remove accidentally committed parser generator
This commit is contained in:
Ayaz 2023-01-11 23:14:52 -06:00 committed by GitHub
commit fdb4fe66ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,384 +0,0 @@
app "generator"
packages {
pf: "https://github.com/roc-lang/basic-cli/releases/download/0.1.3/5SXwdW7rH8QAOnD71IkHcFxCmBEPtFSLAIkclPEgjHQ.tar.br",
}
imports [
pf.Stdout,
pf.File,
pf.Path,
pf.Task.{ Task },
]
provides [main] to pf
RenderTree : [
Text Str,
Items (List RenderTree),
Line (List RenderTree),
Indent (List RenderTree),
Import {modu: List Str, name: Str},
]
renderFile : RenderTree -> Str
renderFile = \tree ->
render (Items [
formatImports (findImports tree),
tree
])
findImports : RenderTree -> Set { modu: (List Str), name: Str }
findImports = \tree ->
when tree is
Text _ -> Set.empty
Items list | Indent list | Line list ->
List.walk list Set.empty \acc, item -> Set.union acc (findImports item)
Import import -> Set.single import
formatImports : Set { modu: (List Str), name: Str } -> RenderTree
formatImports = \set ->
if hasDupImports set then
crash "Duplicate imports!"
else
Items (
set
|> Set.toList
# TODO: Sort by module name
|> List.map \{ modu, name } ->
Line [
Text "use ",
Text (Str.joinWith (List.map modu \m -> Str.concat m "::") ""),
Text name,
Text ";",
]
)
hasDupImports : Set { modu: (List Str), name: Str } -> Bool
hasDupImports = \set ->
nameSet =
set
|> Set.toList
|> List.map \{ modu: _, name } -> name
|> Set.fromList
Set.len nameSet != Set.len nameSet
render : RenderTree -> Str
render = \tree ->
Tuple text _ = renderInner tree 0 Bool.true
text
renderGroup : List RenderTree, Nat, Bool -> [Tuple Str Bool]
renderGroup = \list, indent, newlineBefore ->
List.walk list (Tuple "" newlineBefore) \(Tuple text nlb), item ->
Tuple ntext nla = renderInner item indent nlb
(Tuple
(Str.concat text ntext)
nla
)
renderInner : RenderTree, Nat, Bool -> [Tuple Str Bool]
renderInner = \tree, indent, newlineBefore ->
when tree is
Text text ->
result = if newlineBefore then
Str.concat (Str.repeat " " (4*indent)) text
else
text
Tuple result Bool.false
Items list -> renderGroup list indent newlineBefore
Line list ->
Tuple ntext nla = renderGroup list indent Bool.true
res = if newlineBefore then
# Already added the newline, no need!
ntext
else
Str.concat "\n" ntext
res2 = if nla then
res
else
Str.concat res "\n"
(Tuple res2 Bool.true)
Indent list -> renderGroup list (indent + 1) newlineBefore
Import {modu: _, name} ->
Tuple name Bool.false
parserTrait = \t, e ->
genCall (Import {modu: ["crate", "parser"], name: "Parser"}) [Text "'a", t, e]
parseFunction : Str, RenderTree, RenderTree, RenderTree -> RenderTree
parseFunction = \name, ty, err, body ->
Items [
Line [
Text "pub fn \(name)<'a>() -> impl ",
parserTrait ty err,
Text " {",
],
Indent [body, Line [Text ".trace(\"\(name)\")" ] ],
Line [Text "}"],
Line [Text ""],
]
Type : RenderTree
ErrTy : RenderTree
Parser : [
Loc Parser,
Specialize ErrTy Parser,
Record Str (List { name: Str, parser: Parser }),
Builtin RenderTree Type,
# Named ParserName (World -> Parser),
]
errHeader : Str -> ErrTy
errHeader = \name ->
Items [
Import { modu: ["crate", "parser"], name: "EHeader" },
Text "::",
Text name,
]
fnCall : RenderTree, List RenderTree -> RenderTree
fnCall = \fnName, args ->
Items [
fnName,
Text "(",
Items (List.intersperse args (Text ",")),
Text ")",
]
fn : RenderTree -> (List RenderTree -> RenderTree)
fn = \fnName -> \args -> fnCall fnName args
genCall : RenderTree, List RenderTree -> RenderTree
genCall = \genName, args ->
Items [
genName,
Text "<",
Items (List.intersperse args (Text ", ")),
Text ">",
]
gen : RenderTree -> (List RenderTree -> RenderTree)
gen = \genName -> \args -> genCall genName args
ref : RenderTree -> RenderTree
ref = \name -> Items [Text "&'a ", name]
slice : RenderTree -> RenderTree
slice = \name -> Items [Text "[", name, Text "]"]
refSlice : RenderTree -> RenderTree
refSlice = \name -> ref (slice name)
commentOrNewline = genCall (Import {modu: ["crate", "ast"], name: "CommentOrNewline"}) [ Text "'a" ]
exposedName = genCall (Import {modu: ["crate", "header"], name: "ExposedName"}) [ Text "'a" ]
importsEntry = genCall (Import {modu: ["crate", "header"], name: "ImportsEntry"}) [ Text "'a" ]
uppercaseIdent = genCall (Import {modu: ["crate", "ident"], name: "UppercaseIdent"}) [ Text "'a" ]
moduleName = genCall (Import {modu: ["crate", "header"], name: "ModuleName"}) [ Text "'a" ]
space0E = fn (Import { modu: ["crate", "blankspace"], name: "space0_e" })
keyword = \keywordName ->
Import { modu: ["crate", "header"], name: keywordName }
spaces = \errorName ->
Builtin (space0E [errorName]) (refSlice commentOrNewline)
loc = gen (Import {modu: ["roc_region", "all"], name: "Loc"})
keywordItem = \kw, ty ->
genCall (Import {modu: ["crate", "header"], name: "KeywordItem"}) [ Text "'a", kw, ty ]
collection = \ty ->
genCall (Import {modu: ["crate", "ast"], name: "Collection"}) [ Text "'a", ty ]
spaced = \ty ->
genCall (Import {modu: ["crate", "ast"], name: "Spaced"}) [ Text "'a", ty ]
moduleNameHelp = \err ->
Builtin (fnCall (Import {modu: ["crate", "module"], name: "module_name_help" }) [ err ]) moduleName
exposesValues =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "exposes_values"}) []) (keywordItem (keyword "ExposesKeyword") (collection (loc [spaced exposedName])))
imports =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "imports"}) []) (keywordItem (keyword "ImportsKeyword") (collection (loc [spaced importsEntry])))
generates =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "generates"}) []) (keywordItem (keyword "GeneratesKeyword") uppercaseIdent)
generatesWith =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "generates_with"}) []) (keywordItem (keyword "WithKeyword") (collection (loc [spaced exposedName])))
interfaceHeader = Record "InterfaceHeader" [
{name: "before_name", parser: spaces (errHeader "IndentStart")},
{name: "name", parser: Loc (moduleNameHelp (errHeader "ModuleName"))},
{name: "exposes", parser: Specialize (errHeader "Exposes") exposesValues },
{name: "imports", parser: Specialize (errHeader "Imports") imports },
]
hostedHeader = Record "HostedHeader" [
{name: "before_name", parser: spaces (errHeader "IndentStart")},
{name: "name", parser: Loc (moduleNameHelp (errHeader "ModuleName"))},
{name: "exposes", parser: Specialize (errHeader "Exposes") exposesValues},
{name: "imports", parser: Specialize (errHeader "Imports") imports},
{name: "generates", parser: Specialize (errHeader "Generates") generates},
{name: "generates_with", parser: Specialize (errHeader "GeneratesWith") generatesWith},
]
printCombinatorParserFunction = \parser ->
parseFunction (lowerName (resolveName parser)) (resolveType parser) (Text "EHeader<'a>") (printCombinatorParser parser)
resolveName : Parser -> Str
resolveName = \parser ->
when parser is
Loc _p -> crash "Unnamed parser!"
Specialize _err _p -> crash "Unnamed parser!"
Builtin _name _ty -> crash "Unnamed parser!"
Record name _fields -> name
underscoreScalar = 95
aLowerScalar = 97
aUpperScalar = 65
zUpperScalar = 90
# map from a lower_case_name to a UpperCaseName
upperName : Str -> Str
upperName = \name ->
result = Str.walkScalars name {text: "", needUpper: Bool.true} \{text, needUpper}, c ->
if c == underscoreScalar then
{text, needUpper: Bool.true}
else
newText =
if needUpper then
Str.appendScalar text (c - aLowerScalar + aUpperScalar) |> orCrash
else
Str.appendScalar text c |> orCrash
{text: newText, needUpper: Bool.false}
result.text
expect (upperName "hello_world") == "HelloWorld"
orCrash : Result a e -> a
orCrash = \result ->
when result is
Ok a -> a
Err _e -> crash "orCrash"
lowerName : Str -> Str
lowerName = \name ->
result = Str.walkScalars name {text: "", needUnder: Bool.false} \{text, needUnder}, c ->
newText =
if c >= aUpperScalar && c <= zUpperScalar then
if needUnder then
text
|> Str.appendScalar underscoreScalar
|> orCrash
|> Str.appendScalar (c - aUpperScalar + aLowerScalar)
|> orCrash
else
text
|> Str.appendScalar (c - aUpperScalar + aLowerScalar)
|> orCrash
else
Str.appendScalar text c |> orCrash
{text: newText, needUnder: Bool.true}
result.text
expect
theResult = (lowerName "HelloWorld")
theResult == "hello_world"
resolveType : Parser -> RenderTree
resolveType = \parser ->
when parser is
Loc p -> loc [resolveType p]
Specialize _err p -> resolveType p
Record name _fields -> Items [ Import {modu: ["crate", "generated_ast"], name}, Text "<'a>"]
Builtin _name ty -> ty
printCombinatorParser : Parser -> RenderTree
printCombinatorParser = \parser ->
when parser is
Loc p ->
printed = printCombinatorParser p
value : RenderTree
value = Items [ (Text "loc!("), printed, (Text ")") ]
value
Specialize err p ->
printed = printCombinatorParser p
Items [
Import {modu: ["crate", "parser"], name: "specialize"},
Text "(",
err,
(Text ", "),
printed,
(Text ")"),
]
Record name fields ->
Items [
Text "record!(\(name) {",
(Indent
(fields
|> List.map \f ->
Line [Text "\(f.name): ", printCombinatorParser f.parser, Text ","]
)
),
Text "})"
]
Builtin name _ty -> name
printAst : Parser -> RenderTree
printAst = \parser ->
when parser is
Record name fields ->
Items [
Line [ Text "#[derive(Clone, Debug, PartialEq)]" ],
Line [ Text "pub struct \(name)<'a> {" ],
(Indent (
fields
|> List.map \f ->
Line [Text "pub \(f.name): ", resolveType f.parser, Text ","]
)),
Line [Text "}"],
Line [Text ""],
]
_ -> crash "Not implemented"
expect (render (Text "foo")) == "foo"
expect (render (Line [Text "foo"])) == "foo\n"
expect (render (Indent [Text "foo"])) == " foo"
expect (render (Line [Indent [Text "foo"]])) == " foo\n"
expect
res = (render (Items [Text "{", Indent [Line [Text "foo"]], Text "}"]))
res ==
"""
{
foo
}
"""
allSyntaxItems = [interfaceHeader, hostedHeader]
printedAstItems = Items (allSyntaxItems |> List.map printAst)
printedParserItems = Items (allSyntaxItems |> List.map printCombinatorParserFunction)
# main : Task {} []*
main =
task =
_ <- File.writeUtf8 (Path.fromStr "generated_ast.rs") (renderFile printedAstItems) |> Task.await
File.writeUtf8 (Path.fromStr "generated_parser.rs") (renderFile printedParserItems)
Task.attempt task \result ->
when result is
Ok _ -> Stdout.line "Success!"
Err _e -> Stdout.line "Failed to write file"