cosmicrose
I’m having trouble implementing a parser. Either it enters an infinite recursive loop, or it only parses the first part of the input and drops the rest.
For context, I’m writing a parser for a query language, and it contains the ability to nest boolean expressions. Here’s a stripped-down version of what I’m working with:
defmodule CESQL.Parsec do
import NimbleParsec
value_identifier = ascii_string([?a..?z], min: 1, max: 20)
boolean_operation =
parsec(:expr)
|> ignore(string(" "))
|> choice([
string("AND"),
string("OR"),
string("XOR")
])
|> ignore(string(" "))
|> parsec(:expr)
expr =
choice([
value_identifier,
boolean_operation
])
defparsec :expr, expr
end
My end goal is to parse a boolean expression, and I intend to allow for complex nested expressions like (a AND b) OR c. But for starters, this is what I want out of the above code:
iex> CESQL.Parsec.expr("a AND b")
{:ok, ["a", "AND", "b"], "", _, _, _}
However, when I place value_identifier first in expr’s argument to choice/2, the parser takes the first value and drops the rest of the string, which looks like this:
iex> CESQL.Parsec.expr("a AND b")
{:ok, ["a"], " AND b", _, _, _}
Alternatively, when I place boolean_operation as the first choice, I believe the parser enters an infinite loop trying to find the start of an expression, because my test times out.
How can I get this working the way I want it to? I’ve tried using NimbleParsec.lookahead/2 every way I can think of, but I might be misunderstanding how it works, because I’ve had no luck.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #ai
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 7- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
jakemorrison
I did a lot of parsing of SQL in this project: GitHub - cogini/ecto_extract_migrations: Elixir library to generate Ecto migrations from a PostgreSQL schema SQL file. Uses NimbleParsec and macro-style code generation. · GitHub
It converts a Postgres database schema dump file into Ecto migrations.
cosmicrose
I think I’m actually going to try leex and yecc instead of NimbleParsec. NimbleParsec is awesome, but since I’m trying to implement a query language (the CloudEvents query language), I think it’s more suited to the job. And I only recently discovered this additional feature of Erlang and I’m really excited to use it! For anyone else who wants to parse a language using traditional language-parsing tools, check out Tokenizing and parsing in Elixir with yecc and leex – Andrea Leopardi
jakemorrison
Since there are ABNF grammars for SQL around, you might also look at ex_abnf
kip
Using Leex and Yecc is very workable (and what I used for the fundamentals of ex_cldr). But because parsers are fun, here’s a reasonable attempt at parsing your logical expressions in nimble_parsec using a common approach to de-structuring such parsers:
ityonemo
/Self-promotion but I also have pegasus: Pegasus — pegasus v1.0.0 if you like grammars that actually look like grammars
kip
@ityonemo wow, that’s very cool. Will definitely be taking that for a spin!
TwistingTwists
This post was so useful !
Writing recursive parsers here!
https://github.com/TwistingTwists/swift_class/blob/master/lib/bracket_attributes.ex#L50
Thanks for such insight!