Skip to content

Commit 7885cec

Browse files
authored
Add fl_parse() test tool to call flisp parser directly (JuliaLang/JuliaSyntax.jl#70)
This allows us to call the flisp parser directly instead of using Meta.parse which may have been overridden with the JuliaSyntax parser. Fix the tests to always use the flisp reference parser.
1 parent f68ac76 commit 7885cec

4 files changed

Lines changed: 63 additions & 23 deletions

File tree

JuliaSyntax/src/hooks.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,16 @@ function _core_parser_hook(code, filename, lineno, offset, options)
133133
offset=offset,
134134
code=code)
135135

136-
if VERSION >= v"1.8.0-DEV.1370" # https://github.com/JuliaLang/julia/pull/43876
137-
return Core.Compiler.fl_parse(code, filename, lineno, offset, options)
138-
else
139-
return Core.Compiler.fl_parse(code, filename, offset, options)
140-
end
136+
_fl_parse_hook(code, filename, lineno, offset, options)
137+
end
138+
end
139+
140+
# Call the flisp parser
141+
function _fl_parse_hook(code, filename, lineno, offset, options)
142+
@static if VERSION >= v"1.8.0-DEV.1370" # https://github.com/JuliaLang/julia/pull/43876
143+
return Core.Compiler.fl_parse(code, filename, lineno, offset, options)
144+
else
145+
return Core.Compiler.fl_parse(code, filename, offset, options)
141146
end
142147
end
143148

JuliaSyntax/src/utils.jl

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@ function _printstyled(io::IO, text; fgcolor=nothing, bgcolor=nothing)
2525
end
2626
end
2727

28-
function flisp_parse_all(code; filename="none")
29-
if VERSION >= v"1.6"
30-
Meta.parseall(code, filename=filename)
31-
else
32-
# This is approximate. It should work for well-formed code.
33-
Base.parse_input_line(code, filename=filename)
34-
end
35-
end
36-
3728
# Really remove line numbers, even from Expr(:toplevel)
3829
remove_linenums!(ex) = ex
3930
function remove_linenums!(ex::Expr)
@@ -48,3 +39,49 @@ function remove_linenums!(ex::Expr)
4839
return ex
4940
end
5041

42+
43+
#-------------------------------------------------------------------------------
44+
# Copy of the Meta.parse() API, but ensuring that we call the flisp parser
45+
# rather than using Meta.parse() which may be using the JuliaSyntax parser.
46+
47+
"""
48+
Like Meta.parse() but always call the flisp reference parser.
49+
"""
50+
function fl_parse(str::AbstractString; raise::Bool=true, depwarn::Bool=true)
51+
ex, pos = fl_parse(str, 1, greedy=true, raise=raise, depwarn=depwarn)
52+
if isa(ex,Expr) && ex.head === :error
53+
return ex
54+
end
55+
if pos <= ncodeunits(str)
56+
raise && throw(Meta.ParseError("extra token after end of expression"))
57+
return Expr(:error, "extra token after end of expression")
58+
end
59+
return ex
60+
end
61+
62+
function fl_parse(str::AbstractString, pos::Integer; greedy::Bool=true, raise::Bool=true,
63+
depwarn::Bool=true)
64+
ex, pos = _fl_parse_string(str, "none", 1, pos, greedy ? :statement : :atom)
65+
if raise && isa(ex,Expr) && ex.head === :error
66+
throw(Meta.ParseError(ex.args[1]))
67+
end
68+
return ex, pos
69+
end
70+
71+
"""
72+
Like Meta.parseall() but always call the flisp reference parser.
73+
"""
74+
function fl_parseall(text::AbstractString; filename="none", lineno=1)
75+
ex,_ = _fl_parse_string(text, String(filename), lineno, 1, :all)
76+
return ex
77+
end
78+
79+
function _fl_parse_string(text::AbstractString, filename::AbstractString,
80+
lineno::Integer, index::Integer, options)
81+
if index < 1 || index > ncodeunits(text) + 1
82+
throw(BoundsError(text, index))
83+
end
84+
ex, offset::Int = _fl_parse_hook(text, filename, lineno, index-1, options)
85+
ex, offset+1
86+
end
87+

JuliaSyntax/test/test_utils.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ using JuliaSyntax:
2121
haschildren,
2222
children,
2323
child,
24-
flisp_parse_all
24+
fl_parseall,
25+
fl_parse
2526

2627
function remove_macro_linenums!(ex)
2728
if Meta.isexpr(ex, :macrocall)
@@ -63,7 +64,7 @@ function parsers_agree_on_file(filename; show_diff=false)
6364
# ignore this case.
6465
return true
6566
end
66-
fl_ex = flisp_parse_all(text, filename=filename)
67+
fl_ex = fl_parseall(text, filename=filename)
6768
if Meta.isexpr(fl_ex, :toplevel) && !isempty(fl_ex.args) &&
6869
Meta.isexpr(fl_ex.args[end], (:error, :incomplete))
6970
# Reference parser failed. This generally indicates a broken file not a
@@ -111,7 +112,7 @@ function equals_flisp_parse(tree)
111112
# Reparse with JuliaSyntax. This is a crude way to ensure we're not missing
112113
# some context from the parent node.
113114
ex,_,_ = parse(Expr, node_text)
114-
fl_ex = flisp_parse_all(node_text)
115+
fl_ex = fl_parseall(node_text)
115116
if Meta.isexpr(fl_ex, :error)
116117
return true # Something went wrong in reduction; ignore these cases 😬
117118
end
@@ -237,7 +238,7 @@ function itest_parse(production, code; version::VersionNumber=v"1.6")
237238
println(stdout, "\n\n# Julia Expr:")
238239
show(stdout, MIME"text/plain"(), ex)
239240

240-
f_ex = JuliaSyntax.remove_linenums!(Meta.parse(code, raise=false))
241+
f_ex = JuliaSyntax.remove_linenums!(fl_parse(code, raise=false))
241242
if JuliaSyntax.remove_linenums!(ex) != f_ex
242243
printstyled(stdout, "\n\n# flisp Julia Expr:\n", color=:red)
243244
show(stdout, MIME"text/plain"(), f_ex)

JuliaSyntax/test/tokenize.jl

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module TokenizeTests
44
using Test
55

66
using JuliaSyntax:
7+
JuliaSyntax,
78
@K_str,
89
Kind,
910
kind,
@@ -693,14 +694,10 @@ for op in ops
693694

694695
for (arity, container) in strs
695696
for str in container
696-
expr = Meta.parse(str, raise = false)
697+
expr = JuliaSyntax.fl_parse(str, raise = false)
697698
if VERSION < v"1.7" && str == "a .&& b"
698699
expr = Expr(Symbol(".&&"), :a, :b)
699700
end
700-
if str in (".>:b", ".<:b")
701-
# HACK! See https://github.com/JuliaLang/JuliaSyntax.jl/issues/38
702-
continue
703-
end
704701
if expr isa Expr && (expr.head != :error && expr.head != :incomplete)
705702
tokens = collect(tokenize(str))
706703
exop = expr.head == :call ? expr.args[1] : expr.head

0 commit comments

Comments
 (0)