Skip to content

Commit

Permalink
preserve elseif syntax in parser
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson authored and pkofod committed Aug 5, 2017
1 parent e44071d commit 1fdb84f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 31 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ Language changes
* `{ }` expressions now use `braces` and `bracescat` as expression heads instead
of `cell1d` and `cell2d`, and parse similarly to `vect` and `vcat` ([#8470]).

* Nested `if` expressions that arise from the keyword `elseif` now use `elseif`
as their expression head instead of `if` ([#21774]).

Breaking changes
----------------

Expand Down
22 changes: 15 additions & 7 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,11 @@ function show_block(io::IO, head, args::Vector, body, indent::Int)
print(io, head)
if !isempty(args)
print(io, ' ')
show_list(io, args, ", ", indent)
if head === :elseif
show_list(io, args, " ", indent)
else
show_list(io, args, ", ", indent)
end
end

ind = head === :module || head === :baremodule ? indent : indent + indent_width
Expand Down Expand Up @@ -879,10 +883,19 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
print(io, "function ", args[1], " end")

# block with argument
elseif head in (:for,:while,:function,:if) && nargs==2
elseif head in (:for,:while,:function,:if,:elseif) && nargs==2
show_block(io, head, args[1], args[2], indent)
print(io, "end")

elseif (head === :if || head === :elseif) && nargs == 3
show_block(io, head, args[1], args[2], indent)
if isa(args[3],Expr) && args[3].head == :elseif
show_unquoted(io, args[3], indent, prec)
else
show_block(io, "else", args[3], indent)
print(io, "end")
end

elseif head === :module && nargs==3 && isa(args[1],Bool)
show_block(io, args[1] ? :module : :baremodule, args[2], args[3], indent)
print(io, "end")
Expand Down Expand Up @@ -944,11 +957,6 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
elseif head === :line && 1 <= nargs <= 2
show_linenumber(io, args...)

elseif head === :if && nargs == 3 # if/else
show_block(io, "if", args[1], args[2], indent)
show_block(io, "else", args[3], indent)
print(io, "end")

elseif head === :try && 3 <= nargs <= 4
show_block(io, "try", args[1], indent)
if is_expr(args[3], :block)
Expand Down
9 changes: 4 additions & 5 deletions doc/src/devdocs/ast.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,18 +466,17 @@ if a
b
elseif c
d
else e
f
else
e
end
```

parses as:

```
(if a (block (line 2) b)
(block (line 3) (if c (block (line 4) d)
(block (line 5) e
(line 6) f))))
(elseif (block (line 3) c) (block (line 4) d)
(block (line 5 e))))
```

A `while` loop parses as `(while condition body)`.
Expand Down
20 changes: 11 additions & 9 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1291,31 +1291,33 @@
`(for ,(if (length= ranges 1) (car ranges) (cons 'block ranges))
,body)))

((if)
((if elseif)
(if (newline? (peek-token s))
(error (string "missing condition in \"if\" at " current-filename
":" (- (input-port-line (ts:port s)) 1))))
(let* ((test (parse-cond s))
(let* ((lno (line-number-node s)) ;; line number for elseif condition
(test (parse-cond s))
(test (if (eq? word 'elseif)
`(block ,lno ,test)
test))
(then (if (memq (require-token s) '(else elseif))
'(block)
(parse-block s)))
(nxt (require-token s)))
(take-token s)
(case nxt
((end) (list 'if test then))
((end) (list word test then))
((elseif)
(if (newline? (peek-token s))
(error (string "missing condition in \"elseif\" at " current-filename
":" (- (input-port-line (ts:port s)) 1))))
`(if ,test ,then
;; line number for elseif condition
(block ,(line-number-node s)
,(parse-resword s 'if))))
`(,word ,test ,then
,(parse-resword s 'elseif)))
((else)
(if (eq? (peek-token s) 'if)
(error "use \"elseif\" instead of \"else if\""))
(begin0 (list 'if test then (parse-block s))
(expect-end s word)))
(begin0 (list word test then (parse-block s))
(expect-end s 'if)))
(else (error (string "unexpected \"" nxt "\""))))))
((let)
(let ((binds (if (memv (peek-token s) '(#\newline #\;))
Expand Down
20 changes: 10 additions & 10 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1669,15 +1669,6 @@
(if ,g ,g
,(loop (cdr tail)))))))))))

(define (expand-forms e)
(if (or (atom? e) (memq (car e) '(quote inert top core globalref outerref line module toplevel ssavalue null meta)))
e
(let ((ex (get expand-table (car e) #f)))
(if ex
(ex e)
(cons (car e)
(map expand-forms (cdr e)))))))

(define (expand-for while lhs X body)
;; (for (= lhs X) body)
(let ((coll (make-ssavalue))
Expand Down Expand Up @@ -1884,6 +1875,15 @@
(extract (cdr params) (cons p newparams) whereparams)))))
(extract (cddr e) '() '()))

(define (expand-forms e)
(if (or (atom? e) (memq (car e) '(quote inert top core globalref outerref line module toplevel ssavalue null meta)))
e
(let ((ex (get expand-table (car e) #f)))
(if ex
(ex e)
(cons (car e)
(map expand-forms (cdr e)))))))

;; table mapping expression head to a function expanding that form
(define expand-table
(table
Expand Down Expand Up @@ -3502,7 +3502,7 @@ f(x) = yt(x)
(if value
(compile (cadr e) break-labels value tail)
#f))
((if)
((if elseif)
(let ((test `(gotoifnot ,(compile-cond (cadr e) break-labels) _))
(end-jump `(goto _))
(val (if (and value (not tail)) (new-mutable-var) #f)))
Expand Down
39 changes: 39 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,45 @@ end"""
return
end"""

@test_repr """if a
# line meta
b
end
"""

@test_repr """if a
# line meta
b
elseif c
# line meta
d
end
"""

@test_repr """if a
# line meta
b
elseif c
# line meta
d
else
# line meta
e
end
"""

@test_repr """if a
# line meta
b
elseif c
# line meta
d
elseif e
# line meta
f
end
"""

# issue #7188
@test sprint(show, :foo) == ":foo"
@test sprint(show, Symbol("foo bar")) == "Symbol(\"foo bar\")"
Expand Down

0 comments on commit 1fdb84f

Please sign in to comment.