Megaparsec - Asking for advice on a parsing problem
Hello Haskellers of the internet, I need your help.
I'm currently writing a parser using Megaparsec and have reached a point where I could use some input from smarter coders.
I have a grammar with multiple top-level statements, which can appear any number of times in any order, in EBNF, this would be something like:
topLevelStament -> Variant1 | Variant2
Variant1 -> ...
Variant2 -> ...
For this, I defined the following Haskell types:
data Variant1 = Variant1 String
data Variant2 = Variant2 String
I want the AST to have the following final structure:
data AST = { variants1 :: [Variant1], variants2 :: [Variant2] }
For parsing, I created a type topLevelStament:
data TopLevelStament = V1 Variant1 | V2 Variant2
And use the many and choice parser combinators with backtracking:
variants <- many $ choice [try . parseVariant1, try . parseVariant2]
with individual parsers for each variant:
parseVariant1 :: Parser TopLevelStament
parseVariant2 :: Parser TopLevelStament
Now my question are,
a) is this in general a good approach for my problem? Is it something that I'm missing, something I could do better?
b) what is the best (i.e. most efficient, elegant) way of assembling the AST back from the parsed [TopLevelStament], this is where I am currently struggling the most.
If I have a list of [TopLevelStatement], how can it turn it back into individual [Variant1], [Variant2] lists to assemble the AST?
Thanks a lot and happy haskelling.
Posted Apr 17, 2021, 9:04 PM UTC · edited
The approach seems fine. I'd make a dedicated
parseTopLevelStatementand then dofor your second question, I'd recommend using partitionEithers if you only have two variants. If you plan on extending it, you can just implement it on your own. Here's a hint:
Thanks a lot, I indeed inspired myself a lot from the partitionEiher's implementation:
Fixed formatting.
Hello, MachineGunPablo: code blocks using triple backticks (```) don't work on all versions of Reddit!
Some users see this / this instead.
To fix this, indent every line with 4 spaces instead.
FAQ
^(You can opt out by replying with backtickopt6 to this comment.)