Associativity/quoted order changes between matched_expr vs unmatched_expr

34 views
Skip to first unread message

Luke Imhoff

unread,
Jul 6, 2015, 10:15:58 PM7/6/15
to elixir-l...@googlegroups.com
I'm testing intellij-elixir against elixir-lang/elixir 1.0.4 prior to releasing intellij-elixir 1.0.0.  I'm currently checking my implementation of unmatched_expr and I hit a case in Mix.Tasks.Deps.Clean where my associativity disagrees with native Elixir.  It appears that the left associativity of the operator (in this case `|>`) isn't respected and right-associativity is used when going from an unmatched_expr to a matched_expr.

First, with all matched_expr:

```elixir

one

|> two

|> three

```

and Elixir and intellij-elixir agree the quoting is


```elixir

{

 :|>,

 [line: 3],

 [

  {

   :|>,

   [line: 2],

   [

    {:one, [line: 1], nil},

    {:two, [line: 2], nil}

   ]

  },

  {:three, [line: 3], nil}

 ]

}

```


So, it's left associative (the left-most element are grouped together and they are the left operand to the next `|>` as stated in elixir_parser.yrl#L61)

If the `one` is changed to `one do end`, then it is parsed as a `block_expr` and the `unmatched_expr -> unmatched_expr op_expr` rule goes into effect

```elixir
one do end
|> two
|> three
```

Using `Code.string_to_quoted` this quotes as

```elixir
{
 :|>,
 [line: 2],
 [
  {:one, [line: 1], [[do: nil]]},
   {
    :|>,
    [line: 3],
    [
     {:two, [line: 2], nil},
     {:three, [line: 3], nil}
   ]
  }
 ]
}
```

So, now the associativity has changed and is no longer left, but right.  (Or at least the piping from two to three happens first.)  What am I missing in elixir_parser.yrl or some other part of Code.string_to_quoted that changes the associativity?  This obviously isn't a bug because the `|>` macro rewrites this pipeline correctly, right?  I just want to be mimicking the quoting correctly in intellij-elixir as quote comparison is how I test intellij-elixir's parser

Right now in intellij-elixir I'm preserving left-associativity (by having the same rule order, but unmatched* accepts blocks and matched* doesn't) and getting

```elixir
{
 :|>,
 [line: 3],
 [
  {
   :|>,
   [line: 2],
   [
    {:one, [line: 1], [[do: nil]]},
    {:two, [line: 2], nil}
   ]
  },
  {three,[{line,3}],nil}
 ]
}
```

Which matched the `one |> two |> three` quoted form with the addition of the `[[do: nil]]`.

José Valim

unread,
Jul 7, 2015, 10:20:31 AM7/7/15
to elixir-l...@googlegroups.com
That's an excellent catch Luke!

I was unaware of the current behaviour. It seems what is happening is that the "bar |> baz" ends up being reduced first as the current grammar rules forced so to happen.

It has been solved in master. Breaking the rules apart and making them more explicit solved the issue.

Keep those bugs coming. :) Thank you!

José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/13cd2088-6839-48e0-8ae4-048b04ebb153%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages