Skip to content

Commit

Permalink
fix #24153, make <| right associative (#24243)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Oct 21, 2017
1 parent 33bb56c commit 565601e
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 10 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Language changes
* The parsing of `1<<2*3` as `1<<(2*3)` is deprecated, and will change to
`(1<<2)*3` in a future version ([#13079]).

* The parsing of `<|` is now right associative. `|>` remains left associative ([#24153]).

* `{ }` expressions now use `braces` and `bracescat` as expression heads instead
of `cell1d` and `cell2d`, and parse similarly to `vect` and `vcat` ([#8470]).

Expand Down
3 changes: 2 additions & 1 deletion base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,8 @@ julia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Bas
```
"""
function operator_associativity(s::Symbol)
if operator_precedence(s) in (prec_arrow, prec_assignment, prec_control_flow, prec_power) || isunaryoperator(s) && !is_unary_and_binary_operator(s)
if operator_precedence(s) in (prec_arrow, prec_assignment, prec_control_flow, prec_power) ||
(isunaryoperator(s) && !is_unary_and_binary_operator(s)) || s === :<|
return :right
elseif operator_precedence(s) in (0, prec_comparison) || s in (:+, :++, :*)
return :none
Expand Down
4 changes: 3 additions & 1 deletion doc/src/manual/mathematical-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,9 @@ Julia applies the following order and associativity of operations, from highest
| Multiplication | `* / % & \` | Left[^2] |
| Bitshifts | `<< >> >>>` | Left |
| Addition | `+ - \| ⊻` | Left[^2] |
| Syntax | `: ..` followed by `\|>` | Left |
| Syntax | `: ..` | Left |
| Syntax | `\|>` | Left |
| Syntax | `<\|` | Right |
| Comparisons | `> < >= <= == === != !== <:` | Non-associative |
| Control flow | `&&` followed by `\|\|` followed by `?` | Right |
| Assignments | `= += -= *= /= //= \= ^= ÷= %= \|= &= ⊻= <<= >>= >>>=` | Right |
Expand Down
18 changes: 10 additions & 8 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
(define prec-comparison
(append! '(|<:| |>:| in isa)
(add-dots '(> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩴ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣))))
(define prec-pipe (add-dots '(|\|>| |<\||)))
(define prec-pipe< '(|.<\|| |<\||))
(define prec-pipe> '(|.\|>| |\|>|))
(define prec-colon '(: |..|))
(define prec-plus (append! '($)
(add-dots '(+ - |\|| ⊕ ⊖ ⊞ ⊟ |++| ∪ ∨ ⊔ ± ∓ ∔ ∸ ≂ ≏ ⊎ ⊻ ⊽ ⋎ ⋓ ⧺ ⧻ ⨈ ⨢ ⨣ ⨤ ⨥ ⨦ ⨧ ⨨ ⨩ ⨪ ⨫ ⨬ ⨭ ⨮ ⨹ ⨺ ⩁ ⩂ ⩅ ⩊ ⩌ ⩏ ⩐ ⩒ ⩔ ⩖ ⩗ ⩛ ⩝ ⩡ ⩢ ⩣))))
Expand All @@ -34,7 +35,7 @@

(define prec-names '(prec-assignment
prec-conditional prec-lazy-or prec-lazy-and prec-arrow prec-comparison
prec-pipe prec-colon prec-plus prec-bitshift prec-times prec-rational
prec-pipe< prec-pipe> prec-colon prec-plus prec-bitshift prec-times prec-rational
prec-power prec-decl prec-dot))

(define trans-op (string->symbol ".'"))
Expand Down Expand Up @@ -802,14 +803,14 @@
(define (parse-and s) (parse-RtoL s parse-comparison is-prec-lazy-and? #t parse-and))

(define (parse-comparison s)
(let loop ((ex (parse-pipes s))
(let loop ((ex (parse-pipe< s))
(first #t))
(let ((t (peek-token s)))
(cond ((is-prec-comparison? t)
(begin (take-token s)
(if first
(loop (list 'comparison ex t (parse-pipes s)) #f)
(loop (append ex (list t (parse-pipes s))) #f))))
(loop (list 'comparison ex t (parse-pipe< s)) #f)
(loop (append ex (list t (parse-pipe< s))) #f))))
(first ex)
((length= ex 4)
;; only a single comparison; special chained syntax not required
Expand All @@ -821,7 +822,8 @@
`(call ,op ,arg1 ,arg2))))
(else ex)))))

(define (parse-pipes s) (parse-LtoR s parse-range is-prec-pipe?))
(define (parse-pipe< s) (parse-RtoL s parse-pipe> is-prec-pipe<? #f parse-pipe<))
(define (parse-pipe> s) (parse-LtoR s parse-range is-prec-pipe>?))

; parse ranges and postfix ...
; colon is strange; 3 arguments with 2 colons yields one call:
Expand Down Expand Up @@ -1664,11 +1666,11 @@
#f)
#t)))
#f))
(lhs (parse-pipes s))
(lhs (parse-pipe< s))
(t (peek-token s)))
(cond ((memq t '(= in ∈))
(take-token s)
(let* ((rhs (parse-pipes s))
(let* ((rhs (parse-pipe< s))
(t (peek-token s)))
#;(if (not (or (closing-token? t) (newline? t)))
;; should be: (error "invalid iteration specification")
Expand Down
4 changes: 4 additions & 0 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,10 @@ end

@test parse("1 == 2|>3") == Expr(:call, :(==), 1, Expr(:call, :(|>), 2, 3))

# issue #24153
@test parse("a|>b|>c|>d") == parse("((a|>b)|>c)|>d")
@test parse("a<|b<|c<|d") == parse("a<|(b<|(c<|d))")

# issue #12501 and pr #12502
parse("""
baremodule A
Expand Down

0 comments on commit 565601e

Please sign in to comment.