I’m trying to define a macro whose expansion references a local variable.
Here’s my example:
struct Reference
source::Union{Nothing, LineNumberNode}
registry::Dict
key
end
let
r = Dict()
macro ref(name)
Expr(:call, :Reference, __source__, r, name)
end
@ref("foo")
end
I’d expect this to translate to
let
r = Dict()
Reference(<someLineNumberNode>, f, "foo")
end
but instead, I get the error
ERROR: syntax: macro definition not allowed inside a local scope
Stacktrace:
[1] top-level scope
@ none:1
In CommonLisp I could use MACROLET. Does Julia have anything analogous to this?
Thanks.
Why?
GitHub - MarkNahabedian/AnotherParser.jl allows for a BNF to be constructed as a tree of structs and for that tree to drive the parsing of an input string.
The Dict represented by r
maps non-terminals in a BNF grammar to the syntax associated with that non-terminal. The Reference struct allows for delayed, indirect substitution of a BNF subtree for a specified non-terminal name
.
An example grammar that implements the SemVer version syntax is implemented in AnotherParser.jl/test/SemVerBNF.jl at master · MarkNahabedian/AnotherParser.jl · GitHub.
I can construct a working parser using my struct definitions, but the grammar is diccicult to debug because the structs are not tagged with their source locations.
I have a macro which, for each such struct definition, rewrites the struct to
add a `source` field;
rewrites its constructors to support that field;
defines a macro with the same name as the struct that invokes the constructor with __source__ filled in.
That macro is defined in AnotherParser.jl/src/note_BNFNode_location.jl at master · MarkNahabedian/AnotherParser.jl · GitHub
The BNF node definitions themselves are defined in AnotherParser.jl/src/BNFtypes.jl at master · MarkNahabedian/AnotherParser.jl · GitHub.
I could define a macro which takes the entire grammar and constructs the node tree from that. This would allow me to do a tree walk to replace the shorthand for all of my Reference nodes, but I don’t see how to avoid a tree walk that I fdeel the compiler should do for me were I allowed to define macros in a local scope.