gren-lang / gren-lang/compiler-common

A binops minus sign ("-") split across rows is parsed as negation when the right operand happens to start at the column immediately after the minus sign

Open
#35 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
No language data
Stars
1
Forks
1
PR merge metrics
No merged PRs in 30d

Description

Summary

When a subtraction is written with the right operand on a later row, the parser
reads the - as a unary negation and the whole expression as a function
call
— but only when the right operand happens to start at the column
immediately after the -.

broken =
    10 -
        3

is parsed as 10 (-3) — a call of 10 with the argument -3 — rather than
10 - 3.

The Haskell-based Gren compiler and elm-format both read it as subtraction, unlike
the compiler-common.

The parse

gren-formt --pre-ast on the module above shows:

"body": {
  "value": {
    "type": "call",
    "fn":  { "value": { "type": "number", "value": { "type": "int", "value": 10 } } },
    "args": [
      { "value": { "type": "negate",
                   "expr": { "value": { "type": "number",
                                        "value": { "type": "int", "value": 3 } } } } }
    ]
  }
}

Written on one row, the same expression parses correctly:

sameRow =
    10 - 3
"body": { "value": { "type": "binops",
                     "left":     { "value": { "type": "number", … 10 } },
                     "operator": { "value": "-" },
                     "right":    { "value": { "type": "number", … 3 } } } }
The Haskell-based compiler parses this correctly

Both of these examples compile cleanly with the Haskell-based Gren compiler:

module T exposing (..)


broken : Int
broken =
    10 -
        3


withComment : Int
withComment =
    10 - -- c
        3
$ gren make T
Success! Compiled 1 module.

Diagnosis - it is the column, and nothing else

The trigger is the right operand starting at the column one past the - on a
later row. Nothing about the first operand kinds matters; shifting the operand one
column either way flips the parse.

A blank line between the two rows makes no difference; it is still parsed as a
call.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the split-line and same-row examples with gren-formt --pre-ast, comparing the reported call and binops structures. Trace the parser entry point that handles a binary operator followed by a later-row operand; done when both subtraction examples, including the commented form, produce subtraction rather than a call with negation.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.