Skip to content

Instantly share code, notes, and snippets.

@Swendude
Created March 16, 2020 15:36
Show Gist options
  • Save Swendude/466f0617a6fc61ffa4785cd9cee21967 to your computer and use it in GitHub Desktop.
Save Swendude/466f0617a6fc61ffa4785cd9cee21967 to your computer and use it in GitHub Desktop.
-- I want to parse sentences like these:
-- "There is a #building# over there!"
-- Into types like this:
-- NonTerminal [Token "There is a ", Symbol "building", Token " over there!"
-- However that creates an infite loop
import Parser exposing (..)
type ProdPart
= Symbol String
| Token String
type Production
= Terminal (List ProdPart)
| NonTerminal (List ProdPart)
parseProd : String -> Result (List DeadEnd) Production
parseProd inp =
let
parsed = run productionParser inp
in
case parsed of
Ok pps ->
Ok (NonTerminal pps)
Err errors ->
Err errors
productionParser : Parser (List (ProdPart))
productionParser =
succeed identity
|= loop [] productionHelper
productionHelper : List ProdPart -> Parser (Step (List ProdPart) (List ProdPart))
-- This is where the infinite loop happens
productionHelper parts =
oneOf [
[ tokenParser |> map (\part -> Loop (part :: parts))
,loop "" symbolParser |> map (\part -> Loop (part :: parts))
,end |> (\_ -> succeed (Done (List.reverse parts)))
]
tokenParser : Parser ProdPart
tokenParser =
chompWhile (\c -> c /= '#')
|> getChompedString
|> map (\part -> Token part)
symbolParser : String -> Parser (Step (String) ProdPart)
symbolParser loopChunks =
oneOf [
token "#" |> map (\_ -> Done (Token loopChunks))
, chompWhile (\c -> c /= '#') |> getChompedString |> map (\chunk -> Loop (loopChunks ++ chunk))
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment