mfrasca

mfrasca

I’m rewriting a query parser I have already written in Python twice, with pyparsing/sqlalchemy, and with ply/django. I am now interested in seeing it at work within Elixir. I am VERY new to Elixir, so I’m afraid I’m not yet in the right mindset.

this is the target:
https://github.com/mfrasca/luke/blob/master/src/parser.yrl

and this is the corresponding ply/Python code:
https://github.com/mfrasca/ghini/blob/master/browse/searchgrammar.py

I am not sure about a large amount of issues.

when tokenizing words, I have reserved words, too. in my ply grammar, I let the user write strings quoted or unquoted, but I think I will drop this, to make things easier. or what would you suggest?

are there guidelines / better styles to follow when speaking of Terminals and Nonterminals? I would put Terminals in ALL CAPS, but what’s the impact on the code?

to make an example, is the form ‘[’ preferable to LBRACKET ?

coming from Python, I realise I have the inclination to think I’m producing an object when parsing the query string, and in the end I would evaluate the object, which would be a query. but I guess this is not the way I should think here. I would be building a data structure, which I would then feed to one or more functions (as many as the methods of my python class), defined by pattern-match.

leaving alone when we come to Ecto, where I will need to compute unions and intersections and negations of query sets… and navigating relations between tables… and implementing aggregating functions.

just as an example, these are two legal queries:
taxon where rank.id>=17 and count(verifications)>0
accession where id in [1 5 111] and count(plants.images)>0

it would be of great help getting: code contributions and reviews, reading suggestions, related GPL software sources.

Showing Posts 11 to 20

rvirding

rvirding

Creator of Erlang

Yes, shift-reduce errors can be quite difficult to find and fix. From the very start I sort of dived in at the deep end by implementing leex :wink:, and yecc is actually a very old erlang tool.

mfrasca

mfrasca OP

but I’m wondering … should I be scared of the quoted format. I’m not sure why I should not just produce it from my parser and put it into a macro?

iex(162)> quote do
...(162)> from c in City, where: (c.country == "Sweden") or
...(162)>                        (c.country == "USA" and c.name == "New York")
...(162)> end
{:from, [context: Elixir, import: Ecto.Query],
 [{:in, [context: Elixir, import: Kernel],
   [{:c, [], Elixir}, {:__aliases__, [alias: false], [:City]}]},
  [where: {:or, [context: Elixir, import: Kernel],
           [{:==, [context: Elixir, import: Kernel],
             [{{:., [], [{:c, [], Elixir}, :country]}, [], []}, "Sweden"]},
            {:and, [context: Elixir, import: Kernel],
             [{:==, [context: Elixir, import: Kernel],
               [{{:., [], [{:c, [], Elixir}, :country]}, [], []}, "USA"]},
              {:==, [context: Elixir, import: Kernel],
               [{{:., [], [{:c, [], Elixir}, :name]}, [], []}, "New York"]}
             ]}
           ]}
  ]
 ]}
iex(164)> "city where country='Sweden' or (country='USA' and name='New York')" |>
...(164)> to_charlist() |> :lexer.string() |>                           
...(164)> (fn {_, x, _} -> x end).() |> :parser.parse() |>              
...(164)> (fn {_, x} -> x end).()
{:where, {:domain, 'city'}, 
 {:atom_or, 
  {{:operator, :cmp_eq}, ['country'], 'Sweden'},
  {:atom_and, 
   {{:operator, :cmp_eq}, ['country'], 'USA'},
   {{:operator, :cmp_eq}, ['name'], 'New York'}}}}
tmbb

tmbb

Currently forage only supports intersection, not union. It’s easy to add support for unions, though.

kip

kip

ex_cldr Core Team

Well my first unix was pre-System III and it’s friends lex and yacc. I think they qualify as ancient :slight_smile:

And thanks for writing them as part of Erlang, it feels like they should belong in any build system and it’s great they are standard issue.

rvirding

rvirding

Creator of Erlang

Yes, pre-System III lex and yacc qualify as ancient :wink:

While I did implement leex, I cannot take credit for yecc. The first yecc versions were implemented by another guy at the Ericsson Computer Science Lab, Carl Wilhelm Welin.

mfrasca

mfrasca OP

since I’m here to learn, I would like to go through this macro idea.

I met two difficulties producing that Elixir quote directly from yecc:

  • I’m in Erlang, which I know even less than Elixir,

    so for example the <expression> ::= <expression> or <bterm> production:
    I would write the corresponding action as
    {or, [context: Elixir, import: Kernel], '$1', '$3'}.
    but I get a syntax error before: 'or',
    and once I replace the atom with the string "or", just to see what other problems there are, I get two illegal expression.

    This one works, but is obviously not what I need:
    {"or", [context, "Elixir", import, "Kernel"], '$1', '$3'}.

  • I miss the leading ‘c.’ (and would not want to ask the user to add it).

    I guess than a function in the Erlang code. section can solve this one.

rvirding

rvirding

Creator of Erlang

Some quick comments:

  • in Erlang or is a reserved word, hence the syntax error, so to get the atom you need to write 'or'.
  • the syntax [context: Eiixir, import: Kernel] is illegal so you would have to write [{context,'Elixir'},{import,'Elixir.Kernel'}] to get the corresponding structure. Erlang has very few special syntax cases like Elixir property lists.

c. ?

mfrasca

mfrasca OP

single quoting the or works, thank you. and yes I remembered that the [a: b] was a reduced representation of something else. I could just nor remember what.

the leading c. is the part from c in <table-name> of the Ecto query I’m reconstructing.

in Erlang I’m working with single quoted strings, and in Elixir I need double quoted ones, so I will need a conversion function. but I also need to convert single quoted strings to the corresponding atom. I will review in the light of your hint, and hope to be more specific, but it has to do with the production <query> ::= <domain> where <expression>. I have the name of the table in an Erlang single-quotes string, and I need the atom by that name. like 'City' and I need :City. see above, the third line in the quoted form of the Ecto query.

mfrasca

mfrasca OP

the leading domain (or c.), I can do easily, and the conversion from string to binary and string to atom I also found their names.

so I’m all set I guess,
the single quotes to produce atoms, and the syntax for associative lists, …,
I’ll report here if I manage to get anything working, or at least looking like something that could work.

thank you all!

mfrasca

mfrasca OP

I’m almost there, sorry for the interruptions.

iex> "city where country.code='se' or (country='USA' and name='New York')" |>
...> to_charlist() |> 
...> :lexer.string() |> 
...> (fn {_, x, _} -> x end).() |> 
...> :parser.parse() |> 
...> (fn {_, x} -> x end).()
{:from, [context: Elixir, import: :"Ecto.Query"],
 [
   {:in, [context: Elixir, import: :Kernel],
    [{:domain, [], Elixir}, "city"]},
   [

the rest looks fine to me, but what do I do with this import: :"Ecto.Query", which in my quoted target should look like import: Ecto.Query? same for the :Kernel, what’s that leading colon?

the yecc code looks like this:
query -> domain where expression : {from, [{context, 'Elixir'}, {import, 'Ecto.Query'}], [{in, [{context, 'Elixir'}, {import, 'Kernel'}], [{domain, [], 'Elixir'}, '$1']}, [{where, '$3'}]]}.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews