-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Meta.parsefile
and Meta.parseall
functions as a wrapper around Base.parse_input_line
#34715
Conversation
Base.parse_input_line
and add a docstringBase.parse_input_line
and add docstrings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks potentially useful (could you provide some background on the use cases for this outside Julia?).
I think we might come up with a clearer name if it's going to be a public API, especially because this can consume more than one line when reading from an IO
.
This should be in the The |
How about |
Base.parse_input_line
and add docstringsMeta.parsefile
function as a wrapper around Base.parse_input_line
So far, the only use cases I've found are inside Julia. It comes up for me when I'm trying to do transformations on Julia source code at the source file level (as opposed to on the level of individual expressions). I believe @davidanthoff also has a use case. |
I've changed it to |
FYI - I couldn't figure out where the tests for the |
Yes, I believe that's correct 👍 |
That's a nice name for parsing files but what if a user has the content in a string and they want to parse multiple expressions using the same top level rules that are used for files? For that case I think You should also consider the error handling behavior of |
👍 from triage. |
Triage dixit: This seem fine, but the |
Done! We now always fix up the line number nodes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd approve once the LineNumberNode fixing is deleted from this PR and an issue filed with test cases illustrating where the problem happens.
This allows julia code to more easily consume the output of jl-parse-all (see #34715) and is consistent with the way line number nodes have file name information in all non-toplevel constructs.
❤️ I’ll wait for that PR to be merged, then I’ll remove the "fix line number stuff", rebase on master, etc. |
This allows julia code to more easily consume the output of jl-parse-all (see #34715) and is consistent with the way line number nodes have file name information in all non-toplevel constructs.
It's merged! |
Alright, this should be ready to merge once CI is green. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation looks a lot cleaner now which is great.
I'd still appreciate answers to some previous questions which I don't think were addressed:
- What if someone has the content of the file in a string?
parsefile
taking a file name for opening doesn't seem like the primitive operation here. A more primitive and reusable operation is "parse all code in this string at top level". Better namedparseall
orMeta.parse(..., all=true)
? - What about errors? The behavior of the internal
parse_input_line
may not be what we want here. I feel like error handling should be consistent withMeta.parse()
, or at least documented and tested.
|
||
Parse the Julia source file located at `filename` and return a `:toplevel` | ||
expression that contains all expressions in the file. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when there's a parse error?
I think we should consider making this (a) consistent with Meta.parse
and (b) documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shell> cat test.jl
a = 1
b = 2.2.2
c = 3
julia> parsefile("test.jl")
:($(Expr(:error, "invalid numeric constant \"2.2.\"")))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added to the docstring explaining the behavior when there is a parse error, and I have added some tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this is the right behavior. It doesn't make it possible to emulate include
, which evaluates the expressions before the error. I guess we decided not to do that in the REPL, but I'm not sure why; maybe a REPL input is more of an atomic unit than a file. Anyway it seems to me that should be handled only by the REPL and not a parsing function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I need to sort this out while refactoring the internals so that include
goes via the same code path that we have here. For that it seems we need to return the list of correctly parsed statements, and also include the error somehow (at the end of the list? separately?)
For this user-facing API I'd favor emulating Meta.parse
and the raise
keyword. In fact I'm pretty sure everything should go via Meta.parse
; we've just got to generalize greedy
somehow and allow a filename to be passed.
For greedy
, I'm thinking we should allow specification of grammar rules via rule=:atom
vs rule=:statement
vs rule=:toplevel
? But I'm not sure this is a good general way to enter the current parser and whether it generalizes between parsers. Also we don't have a formal grammar...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we've just got to generalize
greedy
somehow
As you point out, we only seem to need 3 options. I don't have a strong opinion on what the interface should be though; a keyword argument with a few symbol values is not necessarily better than having 2-3 functions.
Also we don't have a formal grammar...
If you really need to talk about specific grammar productions by name, each one is defined by a function called parse-X
, so there you go. But, I really don't think it's too useful to make the exact set of productions part of the interface to parse
. Even grammars written out in BNF will often have rules that are really just implementation details.
I think we need to have both |
Meta.parsefile
function as a wrapper around Base.parse_input_line
Meta.parsefile
and Meta.parseall
functions as a wrapper around Base.parse_input_line
…d `Base.parse_input_line`
Since we are adding the If we really want to replicate error behavior of |
I have no problem switching back to using |
Just FYI we've been discussing this exact issue (from a unifyinig-the-internals viewpoint) over at #35149. I feel like we'll want a single entry point Give me a little time to play with things internally — I think we should hold off on |
This allows julia code to more easily consume the output of jl-parse-all (see JuliaLang#34715) and is consistent with the way line number nodes have file name information in all non-toplevel constructs.
This allows julia code to more easily consume the output of jl-parse-all (see #34715) and is consistent with the way line number nodes have file name information in all non-toplevel constructs.
#35149 is now merged in 1.6-DEV. It includes However, they are not fully fleshed out yet with precisely defined public APIs - I thought this PR would be the logical place to finish doing that. |
Replacement for #34709
This PR adds the
Meta.parsefile
function as a wrapper around the unexportedBase.parse_input_line
.cc: @davidanthoff @cmcaine @timholy