@@ -125,6 +125,10 @@ function textbuf(ps::ParseState)
125
125
textbuf (ps. stream)
126
126
end
127
127
128
+ function first_child_position (ps:: ParseState , pos:: ParseStreamPosition )
129
+ first_child_position (ps. stream, pos)
130
+ end
131
+
128
132
# -------------------------------------------------------------------------------
129
133
# Parser Utils
130
134
@@ -315,7 +319,7 @@ function was_eventually_call(ps::ParseState)
315
319
if kb == K " call"
316
320
return true
317
321
elseif kb == K " where" || kb == K " ::"
318
- p = first_child_position (ps. stream , p)
322
+ p = first_child_position (ps, p)
319
323
else
320
324
return false
321
325
end
@@ -1363,7 +1367,7 @@ function parse_identifier_or_interpolate(ps::ParseState)
1363
1367
# export outer ==> (export outer)
1364
1368
# export ($f) ==> (export ($ f))
1365
1369
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 " )
1367
1371
if ! ok
1368
1372
emit (ps, mark, K " error" , error= " Expected identifier" )
1369
1373
end
@@ -1372,10 +1376,7 @@ end
1372
1376
function finish_macroname (ps, mark, valid_macroname, macro_name_position,
1373
1377
name_kind= nothing )
1374
1378
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)
1379
1380
else
1380
1381
emit (ps, mark, K " error" , error= " not a valid macro name or macro module path" )
1381
1382
end
@@ -1396,7 +1397,8 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1396
1397
# source range of the @-prefixed part of a macro
1397
1398
macro_atname_range = nothing
1398
1399
# $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 . $"
1400
1402
# We record the last component of chains of dot-separated identifiers so we
1401
1403
# know which identifier was the macro name.
1402
1404
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)
1411
1413
# @foo (x,y) ==> (macrocall @foo (tuple x y))
1412
1414
# a().@x y ==> (macrocall (error (. (call a) (quote x))) y)
1413
1415
# [@foo x] ==> (vect (macrocall @foo x))
1416
+ # @var"#" a ==> (macrocall (var @#) a)
1417
+ # A.@var"#" a ==> (macrocall (. A (quote (var @#))) a)
1414
1418
finish_macroname (ps, mark, valid_macroname, macro_name_position)
1415
1419
let ps = with_space_sensitive (ps)
1416
1420
# Space separated macro arguments
@@ -2229,10 +2233,18 @@ function parse_do(ps::ParseState, mark)
2229
2233
emit (ps, mark, K " do" )
2230
2234
end
2231
2235
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)
2236
2248
end
2237
2249
2238
2250
# 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)
2250
2262
# @! x ==> (macrocall @! x)
2251
2263
# @.. x ==> (macrocall @.. x)
2252
2264
# @$ x ==> (macrocall @$ x)
2265
+ # @var"#" x ==> (macrocall (var #) @$ x)
2253
2266
let ps = with_space_sensitive (ps)
2254
2267
parse_atom (ps, false )
2255
2268
end
2256
2269
end
2257
2270
end
2258
2271
2259
- # Parse an identifier, interpolation of @-prefixed symbol
2272
+ # Parse an identifier, interpolation or @-prefixed symbol
2260
2273
#
2261
2274
# flisp: parse-atsym
2262
2275
function parse_atsym (ps:: ParseState )
2263
2276
bump_trivia (ps)
2264
2277
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)
2267
2281
bump (ps, TRIVIA_FLAG)
2268
2282
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))
2270
2284
else
2271
2285
# export a ==> (export a)
2272
2286
# export \n a ==> (export a)
@@ -3322,12 +3336,12 @@ function parse_atom(ps::ParseState, check_identifiers=true)
3322
3336
elseif is_keyword (leading_kind)
3323
3337
if leading_kind == K " var" && (t = peek_token (ps,2 );
3324
3338
kind (t) == K "\" " && ! preceding_whitespace (t))
3325
- # var"x" ==> x
3339
+ # var"x" ==> (var x)
3326
3340
# 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)
3331
3345
#
3332
3346
# NB: Triple quoted var identifiers are not implemented, but with
3333
3347
# the complex deindentation rules they seem like a misfeature
@@ -3344,7 +3358,7 @@ function parse_atom(ps::ParseState, check_identifiers=true)
3344
3358
bump (ps, TRIVIA_FLAG)
3345
3359
else
3346
3360
bump_invisible (ps, K " error" , TRIVIA_FLAG,
3347
- error= " unterminated string literal " )
3361
+ error= " unterminated `var \"\" ` identifier " )
3348
3362
end
3349
3363
t = peek_token (ps)
3350
3364
k = kind (t)
@@ -3354,11 +3368,12 @@ function parse_atom(ps::ParseState, check_identifiers=true)
3354
3368
# var"x") ==> x
3355
3369
# var"x"( ==> x
3356
3370
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" )
3361
3375
end
3376
+ emit (ps, mark, K " var" )
3362
3377
elseif check_identifiers && is_closing_token (ps, leading_kind)
3363
3378
# :(end) ==> (quote (error end))
3364
3379
bump (ps, error= " invalid identifier" )
0 commit comments