Skip to content

Commit 3bd6dff

Browse files
authored
Remove K"parens" from SyntaxNode (#269)
Another approach to fix #239. Elide all `K"parens"` nodes from the `SyntaxNode` tree, replacing them with their single child. With #268 merged, this approach works more neatly and doesn't have the downsides of #265.
1 parent 5bb321a commit 3bd6dff

File tree

4 files changed

+30
-10
lines changed

4 files changed

+30
-10
lines changed

src/parser_api.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ end
7777

7878
function _parse(rule::Symbol, need_eof::Bool, ::Type{T}, text, index=1; version=VERSION,
7979
ignore_trivia=true, filename=nothing, first_line=1, ignore_errors=false,
80-
ignore_warnings=ignore_errors) where {T}
80+
ignore_warnings=ignore_errors, kws...) where {T}
8181
stream = ParseStream(text, index; version=version)
8282
if ignore_trivia && rule != :all
8383
bump_trivia(stream, skip_newlines=true)
@@ -99,7 +99,7 @@ function _parse(rule::Symbol, need_eof::Bool, ::Type{T}, text, index=1; version=
9999
# * It's kind of required for GreenNode, as GreenNode only records spans,
100100
# not absolute positions.
101101
# * Dropping it would be ok for SyntaxNode and Expr...
102-
tree = build_tree(T, stream; wrap_toplevel_as_kind=K"toplevel", filename=filename, first_line=first_line)
102+
tree = build_tree(T, stream; wrap_toplevel_as_kind=K"toplevel", filename=filename, first_line=first_line, kws...)
103103
tree, last_byte(stream) + 1
104104
end
105105

src/syntax_tree.jl

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ end
4444

4545
Base.show(io::IO, ::ErrorVal) = printstyled(io, "", color=:light_red)
4646

47-
function SyntaxNode(source::SourceFile, raw::GreenNode{SyntaxHead}, position::Integer=1)
47+
function SyntaxNode(source::SourceFile, raw::GreenNode{SyntaxHead};
48+
keep_parens=false, position::Integer=1)
49+
_to_SyntaxNode(source, raw, convert(Int, position), keep_parens)
50+
end
51+
52+
function _to_SyntaxNode(source::SourceFile, raw::GreenNode{SyntaxHead},
53+
position::Int, keep_parens::Bool)
4854
if !haschildren(raw) && !(is_syntax_kind(raw) || is_keyword(raw))
4955
# Here we parse the values eagerly rather than representing them as
5056
# strings. Maybe this is good. Maybe not.
@@ -56,10 +62,13 @@ function SyntaxNode(source::SourceFile, raw::GreenNode{SyntaxHead}, position::In
5662
for (i,rawchild) in enumerate(children(raw))
5763
# FIXME: Allowing trivia is_error nodes here corrupts the tree layout.
5864
if !is_trivia(rawchild) || is_error(rawchild)
59-
push!(cs, SyntaxNode(source, rawchild, pos))
65+
push!(cs, _to_SyntaxNode(source, rawchild, pos, keep_parens))
6066
end
6167
pos += rawchild.span
6268
end
69+
if !keep_parens && kind(raw) == K"parens" && length(cs) == 1
70+
return cs[1]
71+
end
6372
node = SyntaxNode(nothing, cs, SyntaxData(source, raw, position, nothing))
6473
for c in cs
6574
c.parent = node
@@ -182,10 +191,11 @@ end
182191
# shallow-copy the data
183192
Base.copy(data::SyntaxData) = SyntaxData(data.source, data.raw, data.position, data.val)
184193

185-
function build_tree(::Type{SyntaxNode}, stream::ParseStream; filename=nothing, first_line=1, kws...)
194+
function build_tree(::Type{SyntaxNode}, stream::ParseStream;
195+
filename=nothing, first_line=1, keep_parens=false, kws...)
186196
green_tree = build_tree(GreenNode, stream; kws...)
187197
source = SourceFile(sourcetext(stream), filename=filename, first_line=first_line)
188-
SyntaxNode(source, green_tree, first_byte(stream))
198+
SyntaxNode(source, green_tree, position=first_byte(stream), keep_parens=keep_parens)
189199
end
190200

191201
#-------------------------------------------------------------------------------

test/expr.jl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
(s; kws...) -> JuliaSyntax.parsestmt(Expr, s; kws...),
66
(s; kws...) -> JuliaSyntax.parseall(Expr, s; kws...))
77
else
8-
((s; kws...) -> Expr(JuliaSyntax.parseatom(SyntaxNode, s; kws...)),
9-
(s; kws...) -> Expr(JuliaSyntax.parsestmt(SyntaxNode, s; kws...)),
10-
(s; kws...) -> Expr(JuliaSyntax.parseall(SyntaxNode, s; kws...)))
8+
((s; kws...) -> Expr(JuliaSyntax.parseatom(SyntaxNode, s; keep_parens=true, kws...)),
9+
(s; kws...) -> Expr(JuliaSyntax.parsestmt(SyntaxNode, s; keep_parens=true, kws...)),
10+
(s; kws...) -> Expr(JuliaSyntax.parseall(SyntaxNode, s; keep_parens=true, kws...)))
1111
end
1212

1313
@testset "Quote nodes" begin
@@ -534,6 +534,16 @@
534534
@test parsestmt("return") == Expr(:return, nothing)
535535
end
536536

537+
@testset "Large integer macros" begin
538+
@test parsestmt("0x00000000000000001") ==
539+
Expr(:macrocall, GlobalRef(Core, Symbol("@uint128_str")),
540+
nothing, "0x00000000000000001")
541+
542+
@test parsestmt("(0x00000000000000001)") ==
543+
Expr(:macrocall, GlobalRef(Core, Symbol("@uint128_str")),
544+
nothing, "0x00000000000000001")
545+
end
546+
537547
@testset "struct" begin
538548
@test parsestmt("struct A end") ==
539549
Expr(:struct, false, :A, Expr(:block, LineNumberNode(1)))

test/parser.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ function parse_to_sexpr_str(production, code::AbstractString; v=v"1.6", expr=fal
77
JuliaSyntax.validate_tokens(stream)
88
t = build_tree(GreenNode, stream, wrap_toplevel_as_kind=K"None")
99
source = SourceFile(code)
10-
s = SyntaxNode(source, t)
10+
s = SyntaxNode(source, t, keep_parens=true)
1111
if expr
1212
JuliaSyntax.remove_linenums!(Expr(s))
1313
else

0 commit comments

Comments
 (0)