@@ -125,6 +125,10 @@ function textbuf(ps::ParseState)
125125 textbuf (ps. stream)
126126end
127127
128+ function first_child_position (ps:: ParseState , pos:: ParseStreamPosition )
129+ first_child_position (ps. stream, pos)
130+ end
131+
128132# -------------------------------------------------------------------------------
129133# Parser Utils
130134
@@ -315,7 +319,7 @@ function was_eventually_call(ps::ParseState)
315319 if kb == K " call"
316320 return true
317321 elseif kb == K " where" || kb == K " ::"
318- p = first_child_position (ps. stream , p)
322+ p = first_child_position (ps, p)
319323 else
320324 return false
321325 end
@@ -1363,7 +1367,7 @@ function parse_identifier_or_interpolate(ps::ParseState)
13631367 # export outer ==> (export outer)
13641368 # export ($f) ==> (export ($ f))
13651369 ok = (b. is_leaf && (b. kind == K " Identifier" || is_operator (b. kind))) ||
1366- (! b. is_leaf && b. kind == K " $ " )
1370+ (! b. is_leaf && b. kind in KSet " $ var " )
13671371 if ! ok
13681372 emit (ps, mark, K " error" , error= " Expected identifier" )
13691373 end
@@ -1372,10 +1376,7 @@ end
13721376function finish_macroname (ps, mark, valid_macroname, macro_name_position,
13731377 name_kind= nothing )
13741378 if valid_macroname
1375- if isnothing (name_kind)
1376- name_kind = macro_name_kind (peek_behind (ps, macro_name_position). kind)
1377- end
1378- reset_node! (ps, macro_name_position, kind = name_kind)
1379+ fix_macro_name_kind! (ps, macro_name_position, name_kind)
13791380 else
13801381 emit (ps, mark, K " error" , error= " not a valid macro name or macro module path" )
13811382 end
@@ -1396,7 +1397,8 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
13961397 # source range of the @-prefixed part of a macro
13971398 macro_atname_range = nothing
13981399 # $A.@x ==> (macrocall (. ($ A) (quote @x)))
1399- valid_macroname = peek_behind (ps, skip_trivia= false ). kind in KSet " Identifier . $"
1400+ # A.@var"#" ==> (macrocall (. A (quote @x)))
1401+ valid_macroname = peek_behind (ps, skip_trivia= false ). kind in KSet " Identifier var . $"
14001402 # We record the last component of chains of dot-separated identifiers so we
14011403 # know which identifier was the macro name.
14021404 macro_name_position = position (ps) # points to same output span as peek_behind
@@ -1411,6 +1413,8 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
14111413 # @foo (x,y) ==> (macrocall @foo (tuple x y))
14121414 # a().@x y ==> (macrocall (error (. (call a) (quote x))) y)
14131415 # [@foo x] ==> (vect (macrocall @foo x))
1416+ # @var"#" a ==> (macrocall (var @#) a)
1417+ # A.@var"#" a ==> (macrocall (. A (quote (var @#))) a)
14141418 finish_macroname (ps, mark, valid_macroname, macro_name_position)
14151419 let ps = with_space_sensitive (ps)
14161420 # Space separated macro arguments
@@ -2229,10 +2233,18 @@ function parse_do(ps::ParseState, mark)
22292233 emit (ps, mark, K " do" )
22302234end
22312235
2232- function macro_name_kind (k)
2233- return k == K " Identifier" ? K " MacroName" :
2234- k == K " ." ? K " @." :
2235- internal_error (" unrecognized source kind for macro name " , k)
2236+ function fix_macro_name_kind! (ps:: ParseState , macro_name_position, name_kind= nothing )
2237+ k = peek_behind (ps, macro_name_position). kind
2238+ if k == K " var"
2239+ macro_name_position = first_child_position (ps, macro_name_position)
2240+ k = peek_behind (ps, macro_name_position). kind
2241+ end
2242+ if isnothing (name_kind)
2243+ name_kind = k == K " Identifier" ? K " MacroName" :
2244+ k == K " ." ? K " @." :
2245+ internal_error (" unrecognized source kind for macro name " , k)
2246+ end
2247+ reset_node! (ps, macro_name_position, kind= name_kind)
22362248end
22372249
22382250# If remap_kind is false, the kind will be remapped by parse_call_chain after
@@ -2250,23 +2262,25 @@ function parse_macro_name(ps::ParseState)
22502262 # @! x ==> (macrocall @! x)
22512263 # @.. x ==> (macrocall @.. x)
22522264 # @$ x ==> (macrocall @$ x)
2265+ # @var"#" x ==> (macrocall (var #) @$ x)
22532266 let ps = with_space_sensitive (ps)
22542267 parse_atom (ps, false )
22552268 end
22562269 end
22572270end
22582271
2259- # Parse an identifier, interpolation of @-prefixed symbol
2272+ # Parse an identifier, interpolation or @-prefixed symbol
22602273#
22612274# flisp: parse-atsym
22622275function parse_atsym (ps:: ParseState )
22632276 bump_trivia (ps)
22642277 if peek (ps) == K " @"
2265- # export @a ==> (export @a)
2266- # export a, \n @b ==> (export a @b)
2278+ # export @a ==> (export @a)
2279+ # export @var"'" ==> (export (var @'))
2280+ # export a, \n @b ==> (export a @b)
22672281 bump (ps, TRIVIA_FLAG)
22682282 parse_macro_name (ps)
2269- reset_node ! (ps, position (ps), kind = macro_name_kind ( peek_behind (ps) . kind ))
2283+ fix_macro_name_kind ! (ps, position (ps))
22702284 else
22712285 # export a ==> (export a)
22722286 # export \n a ==> (export a)
@@ -3322,12 +3336,12 @@ function parse_atom(ps::ParseState, check_identifiers=true)
33223336 elseif is_keyword (leading_kind)
33233337 if leading_kind == K " var" && (t = peek_token (ps,2 );
33243338 kind (t) == K "\" " && ! preceding_whitespace (t))
3325- # var"x" ==> x
3339+ # var"x" ==> (var x)
33263340 # Raw mode unescaping
3327- # var"" ==>
3328- # var"\"" ==> "
3329- # var"\\"" ==> \"
3330- # var"\\x" ==> \\x
3341+ # var"" ==> (var )
3342+ # var"\"" ==> (var ")
3343+ # var"\\"" ==> (var \")
3344+ # var"\\x" ==> (var \\x)
33313345 #
33323346 # NB: Triple quoted var identifiers are not implemented, but with
33333347 # the complex deindentation rules they seem like a misfeature
@@ -3344,7 +3358,7 @@ function parse_atom(ps::ParseState, check_identifiers=true)
33443358 bump (ps, TRIVIA_FLAG)
33453359 else
33463360 bump_invisible (ps, K " error" , TRIVIA_FLAG,
3347- error= " unterminated string literal " )
3361+ error= " unterminated `var \"\" ` identifier " )
33483362 end
33493363 t = peek_token (ps)
33503364 k = kind (t)
@@ -3354,11 +3368,12 @@ function parse_atom(ps::ParseState, check_identifiers=true)
33543368 # var"x") ==> x
33553369 # var"x"( ==> x
33563370 else
3357- # var"x"end ==> (error (end ))
3358- # var"x"1 ==> (error 1 )
3359- # var"x"y ==> (error y )
3360- bump (ps, error= " suffix not allowed after var\" ...\" syntax" )
3371+ # var"x"end ==> (var x (error-t ))
3372+ # var"x"1 ==> (var x (error-t) )
3373+ # var"x"y ==> (var x (error-t) )
3374+ bump (ps, TRIVIA_FLAG, error= " suffix not allowed after var\" ...\" syntax" )
33613375 end
3376+ emit (ps, mark, K " var" )
33623377 elseif check_identifiers && is_closing_token (ps, leading_kind)
33633378 # :(end) ==> (quote (error end))
33643379 bump (ps, error= " invalid identifier" )
0 commit comments