Skip to content

Commit 19ec995

Browse files
committed
nough ncat and nrow parsing for now
1 parent b19d81d commit 19ec995

File tree

3 files changed

+123
-99
lines changed

3 files changed

+123
-99
lines changed

src/components/lists.jl

Lines changed: 114 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -82,124 +82,140 @@ function parse_array(ps::ParseState, isref = false)
8282
end
8383
push!(trivia, accept_rsquare(ps))
8484
if dims > 1
85-
pushfirst!(args, EXPR(Symbol(dims), 0, 0, ""))
86-
return EXPR(:ncat, args, trivia)
85+
ret = EXPR(:ncat, args, trivia)
86+
pushfirst!(ret, EXPR(Symbol(dims), 0, 0, ""))
87+
return ret
8788
else
8889
return EXPR(:vect, args, trivia)
8990
end
9091
else
91-
first_arg = @nocloser ps :newline @closesquare ps @closer ps :insquare @closer ps :ws @closer ps :wsop @closer ps :comma parse_expression(ps)
92-
if isref && _do_kw_convert(ps, first_arg)
93-
first_arg = _kw_convert(first_arg)
94-
end
92+
ret = parse_array_outer(ps::ParseState, trivia, isref)
9593

96-
if kindof(ps.nt) === Tokens.RSQUARE
97-
if headof(first_arg) === :generator || headof(first_arg) === :flatten
98-
push!(trivia, accept_rsquare(ps))
99-
if isbinarycall(first_arg.args[1]) && is_pairarrow(first_arg.args[1].args[2])
100-
return EXPR(:dict_comprehension, EXPR[first_arg], trivia)
101-
else
102-
return EXPR(:comprehension, EXPR[first_arg], trivia)
103-
end
104-
elseif kindof(ps.ws) == SemiColonWS
105-
dims = count_semicolons(ps)
106-
push!(args, first_arg)
107-
push!(trivia, accept_rsquare(ps))
108-
if dims > 1
109-
pushfirst!(args, EXPR(Symbol(dims), 0, 0, ""))
110-
return EXPR(:ncat, args, trivia)
111-
else
112-
return EXPR(:vcat, args, trivia)
113-
end
114-
else
115-
push!(args, first_arg)
116-
push!(trivia, accept_rsquare(ps))
117-
ret = EXPR(:vect, args, trivia)
118-
end
119-
elseif iscomma(ps.nt)
120-
push!(args, first_arg)
121-
push!(trivia, accept_comma(ps))
122-
@closesquare ps parse_comma_sep(ps, args, trivia, isref, insert_params_at = 1)
123-
push!(trivia, accept_rsquare(ps))
124-
return EXPR(:vect, args, trivia)
125-
elseif kindof(ps.ws) == WS || kindof(ps.ws) == SemiColonWS || kindof(ps.ws) == NewLineWS
126-
ps.closer.inref = false
127-
args1 = EXPR[first_arg]
128-
prevpos = position(ps)
129-
ncatdims = 0
130-
while kindof(ps.nt) !== Tokens.RSQUARE && kindof(ps.ws) !== NewLineWS && kindof(ps.ws) !== SemiColonWS && kindof(ps.nt) !== Tokens.ENDMARKER
131-
a = @closesquare ps @closer ps :ws @closer ps :wsop parse_expression(ps)
132-
push!(args1, a)
94+
pushtotrivia!(ret, accept_rsquare(ps))
95+
return ret
96+
end
97+
return ret
98+
end
13399

134-
prevpos = loop_check(ps, prevpos)
135-
end
136-
if kindof(ps.ws) === SemiColonWS
137-
ncatdims = count_semicolons(ps)
138-
end
139-
if kindof(ps.nt) === Tokens.RSQUARE && kindof(ps.ws) != SemiColonWS
140-
push!(trivia, accept_rsquare(ps))
141-
if length(args1) == 1
142-
return EXPR(:vcat, args1, trivia)
143-
else
144-
return EXPR(:hcat, args1, trivia)
145-
end
146-
else
147-
if length(args1) == 1
148-
first_row = args1[1]
149-
else
150-
first_row = EXPR(:row, args1, nothing)
151-
end
152-
push!(args, first_row)
153-
prevpos = position(ps)
154-
while kindof(ps.nt) !== Tokens.RSQUARE && kindof(ps.nt) !== Tokens.ENDMARKER
155-
thisdims = 0
156-
first_arg = @closesquare ps @closer ps :ws @closer ps :wsop parse_expression(ps)
157-
args2 = EXPR[first_arg]
158-
prevpos1 = position(ps)
159-
while kindof(ps.nt) !== Tokens.RSQUARE && kindof(ps.ws) !== NewLineWS && kindof(ps.ws) !== SemiColonWS && kindof(ps.nt) !== Tokens.ENDMARKER
160-
a = @closesquare ps @closer ps :ws @closer ps :wsop parse_expression(ps)
100+
binding_power(ps) =
101+
if kindof(ps.ws) == Tokens.SEMICOLON_WS
102+
-count_semicolons(ps)
103+
elseif kindof(ps.ws) == Tokens.NEWLINE_WS
104+
-1
105+
elseif kindof(ps.ws) == Tokens.WS
106+
0
107+
else
108+
1
109+
end
161110

162-
push!(args2, a)
163-
prevpos1 = loop_check(ps, prevpos1)
164-
end
165-
if kindof(ps.ws) === SemiColonWS
166-
thisdims = count_semicolons(ps)
167-
if thisdims > ncatdims
168-
ncatdims = thisdims
169-
end
111+
function parse_array_outer(ps::ParseState, trivia, isref)
112+
args_list = EXPR[]
113+
trivia_list = Any[]
114+
trivia_bp = Int[]
115+
min_bp = 0
116+
is_start = true
117+
while kindof(ps.nt) !== Tokens.RSQUARE && kindof(ps.nt) !== Tokens.ENDMARKER
118+
a = @nocloser ps :newline @closesquare ps @closer ps :insquare @closer ps :ws @closer ps :wsop @closer ps :comma parse_expression(ps)
119+
if is_start
120+
args = EXPR[]
121+
if isref && _do_kw_convert(ps, a)
122+
a = _kw_convert(a)
123+
end
124+
if kindof(ps.nt) === Tokens.RSQUARE
125+
if headof(a) === :generator || headof(a) === :flatten
126+
if isbinarycall(a.args[1]) && is_pairarrow(a.args[1].args[2])
127+
return EXPR(:dict_comprehension, EXPR[a], trivia)
128+
else
129+
return EXPR(:comprehension, EXPR[a], trivia)
170130
end
171-
# if only one entry dont use :row
172-
if length(args2) == 1
173-
push!(args, args2[1])
131+
elseif kindof(ps.ws) == SemiColonWS
132+
dims = count_semicolons(ps)
133+
push!(args, a)
134+
if dims > 1
135+
ret = EXPR(:ncat, args, trivia)
136+
pushfirst!(ret, EXPR(Symbol(dims), 0, 0, ""))
137+
return ret
174138
else
175-
if thisdims > 1
176-
pushfirst!(args2, EXPR(Symbol(thisdims), 0, 0, ""))
177-
push!(args, EXPR(:nrow, args2, nothing))
178-
else
179-
push!(args, EXPR(:row, args2, nothing))
180-
end
139+
return EXPR(:vcat, args, trivia)
181140
end
182-
prevpos = loop_check(ps, prevpos)
183-
end
184-
push!(trivia, accept_rsquare(ps))
185-
if ncatdims > 1
186-
pushfirst!(args, EXPR(Symbol(ncatdims), 0, 0, ""))
187-
return EXPR(:ncat, args, trivia)
188141
else
189-
return EXPR(:vcat, args, trivia)
142+
push!(args, a)
143+
return EXPR(:vect, args, trivia)
190144
end
145+
elseif iscomma(ps.nt)
146+
args = EXPR[]
147+
push!(args, a)
148+
push!(trivia, accept_comma(ps))
149+
@closesquare ps parse_comma_sep(ps, args, trivia, isref, insert_params_at = 1)
150+
return EXPR(:vect, args, trivia)
191151
end
152+
end
153+
is_start = false
154+
push!(args_list, a)
155+
push!(trivia_list, ps.ws)
156+
bp = binding_power(ps)
157+
bp < min_bp && (min_bp = bp)
158+
if bp <= 0
159+
push!(trivia_bp, bp)
160+
end
161+
end
162+
ret = _process_inner_array(args_list, trivia_bp)
163+
for t in trivia
164+
pushtotrivia!(ret, t)
165+
end
166+
167+
if ret.head === :nrow
168+
if min_bp == 0
169+
popfirst!(ret.args)
170+
ret.head = :hcat
171+
elseif min_bp == -1
172+
popfirst!(ret.args)
173+
ret.head = :vcat
192174
else
193-
push!(args, first_arg)
194-
push!(trivia, accept_rsquare(ps))
195-
ret = EXPR(:vect, args, trivia)
175+
ret.head = :ncat
196176
end
177+
elseif min_bp == 0
178+
ret.head = :hcat
179+
elseif min_bp == -1
180+
ret.head = :vcat
197181
end
182+
198183
return ret
199184
end
200185

201-
function parse_array_row()
186+
function _process_inner_array(args_list, trivia_bp)
187+
if isempty(trivia_bp)
188+
return only(args_list)
189+
end
190+
bp = minimum(trivia_bp)
191+
if all(==(bp), trivia_bp)
192+
if bp == 0
193+
ret = EXPR(:row, EXPR[], EXPR[])
194+
else
195+
ret = EXPR(:nrow, copy(args_list), EXPR[])
196+
pushfirst!(ret, EXPR(Symbol(-bp), 0, 0, ""))
197+
end
198+
end
202199

200+
i = 1
201+
i0 = 1
202+
if bp == 0
203+
ret = EXPR(:row, EXPR[], EXPR[])
204+
else
205+
ret = EXPR(:nrow, EXPR[], EXPR[])
206+
push!(ret, EXPR(Symbol(-bp), 0, 0, ""))
207+
end
208+
while true
209+
i = findnext(==(bp), trivia_bp, i0)
210+
i === nothing && (i = length(args_list))
211+
inner_args = args_list[i0:i]
212+
inner_trivia = trivia_bp[i0:(i-1)]
213+
i0 = i + 1
214+
215+
push!(ret, _process_inner_array(inner_args, inner_trivia))
216+
i >= length(args_list) && break
217+
end
218+
return ret
203219
end
204220

205221
"""

src/iterate.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function _getindex(x::EXPR, i)
108108
_quotenode(x, i)
109109
elseif headof(x) === :ref
110110
_call(x, i)
111-
elseif headof(x) === :row
111+
elseif headof(x) === :row || headof(x) === :nrow
112112
x.args[i]
113113
elseif headof(x) === :string
114114
_string(x, i)

test/parser.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,11 @@ end
502502
@test "[x;;; y;;;z]" |> test_expr
503503
end
504504

505+
@testset "ncat" begin
506+
@test "[1 2; 3 4]" |> test_expr
507+
@test "[1;2;;3;4;;5;6;;;;9]" |> test_expr
508+
end
509+
505510
@testset "typed_ncat" begin
506511
@test "t[;;]" |> test_expr
507512
@test "t[;;;;;;;]" |> test_expr
@@ -1216,6 +1221,9 @@ end
12161221
@test test_expr("a'")
12171222
@test test_expr("a''")
12181223
@test test_expr("a'''")
1224+
# @test test_expr(":.'")
1225+
# @test test_expr(":?'")
1226+
# @test test_expr(":a'")
12191227
end
12201228

12211229
@testset "end as id juxt" begin

0 commit comments

Comments
 (0)