@@ -371,7 +371,7 @@ function parse_RtoL(ps::ParseState, down, is_op, self)
371371 down (ps)
372372 isdot, tk = peek_dotted_op_token (ps)
373373 if is_op (tk)
374- bump_dotted (ps, isdot, remap_kind= K " Identifier" )
374+ bump_dotted (ps, isdot, tk, remap_kind= K " Identifier" )
375375 self (ps)
376376 emit (ps, mark, isdot ? K " dotcall" : K " call" , INFIX_FLAG)
377377 end
@@ -598,7 +598,7 @@ function parse_assignment_with_initial_ex(ps::ParseState, mark, down::T) where {
598598 # a .~ b ==> (dotcall-i a ~ b)
599599 # [a ~ b c] ==> (hcat (call-i a ~ b) c)
600600 # [a~b] ==> (vect (call-i a ~ b))
601- bump_dotted (ps, isdot, remap_kind= K " Identifier" )
601+ bump_dotted (ps, isdot, t, remap_kind= K " Identifier" )
602602 bump_trivia (ps)
603603 parse_assignment (ps, down)
604604 emit (ps, mark, isdot ? K " dotcall" : K " call" , INFIX_FLAG)
@@ -617,7 +617,7 @@ function parse_assignment_with_initial_ex(ps::ParseState, mark, down::T) where {
617617 (- 1 , K " Identifier" , EMPTY_FLAGS), # op
618618 (1 , K " =" , TRIVIA_FLAG))
619619 else
620- bump_dotted (ps, isdot, TRIVIA_FLAG)
620+ bump_dotted (ps, isdot, t, TRIVIA_FLAG)
621621 end
622622 bump_trivia (ps)
623623 # Syntax Edition TODO : We'd like to call `down` here when
@@ -743,7 +743,7 @@ function parse_arrow(ps::ParseState)
743743 # x <--> y ==> (call-i x <--> y)
744744 # x .--> y ==> (dotcall-i x --> y)
745745 # x -->₁ y ==> (call-i x -->₁ y)
746- bump_dotted (ps, isdot, remap_kind= K " Identifier" )
746+ bump_dotted (ps, isdot, t, remap_kind= K " Identifier" )
747747 parse_arrow (ps)
748748 emit (ps, mark, isdot ? K " dotcall" : K " call" , INFIX_FLAG)
749749 end
@@ -771,7 +771,7 @@ function parse_lazy_cond(ps::ParseState, down, is_op, self)
771771 (isdot, t) = peek_dotted_op_token (ps)
772772 k = kind (t)
773773 if is_op (k)
774- bump_dotted (ps, isdot, TRIVIA_FLAG)
774+ bump_dotted (ps, isdot, t, TRIVIA_FLAG)
775775 self (ps)
776776 emit (ps, mark, isdot ? dotted (k) : k, flags (t))
777777 if isdot
@@ -819,7 +819,7 @@ function parse_comparison(ps::ParseState, subtype_comparison=false)
819819 while ((isdot, t) = peek_dotted_op_token (ps); is_prec_comparison (t))
820820 n_comparisons += 1
821821 op_dotted = isdot
822- op_pos = bump_dotted (ps, isdot, emit_dot_node= true , remap_kind= K " Identifier" )
822+ op_pos = bump_dotted (ps, isdot, t, emit_dot_node= true , remap_kind= K " Identifier" )
823823 parse_pipe_lt (ps)
824824 end
825825 if n_comparisons == 1
@@ -873,15 +873,16 @@ end
873873function parse_range (ps:: ParseState )
874874 mark = position (ps)
875875 parse_invalid_ops (ps)
876+
876877 (initial_dot, initial_tok) = peek_dotted_op_token (ps)
877878 initial_kind = kind (initial_tok)
878- if initial_kind != K " :" && is_prec_colon (initial_kind)
879- # a..b ==> (call-i a .. b)
879+ if initial_kind != K " :" && ( is_prec_colon (initial_kind) || (initial_dot && initial_kind == K " . " ) )
880+ # a..b ==> (call-i a (dots-2) b)
880881 # a … b ==> (call-i a … b)
881882 # a .… b ==> (dotcall-i a … b)
882- bump_dotted (ps, initial_dot, remap_kind= K " Identifier" )
883+ bump_dotted (ps, initial_dot, initial_tok, remap_kind= K " Identifier" )
883884 parse_invalid_ops (ps)
884- emit (ps, mark, initial_dot ? K " dotcall" : K " call" , INFIX_FLAG)
885+ emit (ps, mark, ( initial_dot && initial_kind != K " . " ) ? K " dotcall" : K " call" , INFIX_FLAG)
885886 elseif initial_kind == K " :" && ps. range_colon_enabled
886887 # a ? b : c:d ==> (? a b (call-i c : d))
887888 n_colons = 0
@@ -948,8 +949,10 @@ function parse_range(ps::ParseState)
948949 # x... ==> (... x)
949950 # x:y... ==> (... (call-i x : y))
950951 # x..y... ==> (... (call-i x .. y)) # flisp parser fails here
951- if peek (ps) == K " .. ."
952+ if peek (ps) == K " ." && peek (ps, 2 ) == K " . " && peek (ps, 3 ) == K " ."
952953 bump (ps, TRIVIA_FLAG)
954+ bump (ps, TRIVIA_FLAG) # second dot
955+ bump (ps, TRIVIA_FLAG) # third dot
953956 emit (ps, mark, K " ..." )
954957 end
955958end
@@ -965,7 +968,7 @@ function parse_invalid_ops(ps::ParseState)
965968 parse_expr (ps)
966969 while ((isdot, t) = peek_dotted_op_token (ps); kind (t) in KSet " ErrorInvalidOperator Error**" )
967970 bump_trivia (ps)
968- bump_dotted (ps, isdot)
971+ bump_dotted (ps, isdot, t )
969972 parse_expr (ps)
970973 emit (ps, mark, isdot ? K " dotcall" : K " call" , INFIX_FLAG)
971974 end
@@ -1006,7 +1009,7 @@ function parse_with_chains(ps::ParseState, down, is_op, chain_ops)
10061009 # [x+y + z] ==> (vect (call-i x + y z))
10071010 break
10081011 end
1009- bump_dotted (ps, isdot, remap_kind= K " Identifier" )
1012+ bump_dotted (ps, isdot, t, remap_kind= K " Identifier" )
10101013 down (ps)
10111014 if kind (t) in chain_ops && ! is_suffixed (t) && ! isdot
10121015 # a + b + c ==> (call-i a + b c)
@@ -1258,7 +1261,7 @@ function parse_unary(ps::ParseState)
12581261 #
12591262 # (The flisp parser only considers commas before `;` and thus gets this
12601263 # last case wrong)
1261- op_pos = bump_dotted (ps, op_dotted, emit_dot_node= true , remap_kind= K " Identifier" )
1264+ op_pos = bump_dotted (ps, op_dotted, op_t, emit_dot_node= true , remap_kind= K " Identifier" )
12621265
12631266 space_before_paren = preceding_whitespace (t2)
12641267 if space_before_paren
@@ -1352,12 +1355,12 @@ function parse_unary(ps::ParseState)
13521355 # -0x1 ==> (call-pre - 0x01)
13531356 # - 2 ==> (call-pre - 2)
13541357 # .-2 ==> (dotcall-pre - 2)
1355- op_pos = bump_dotted (ps, op_dotted, remap_kind= K " Identifier" )
1358+ op_pos = bump_dotted (ps, op_dotted, op_t, remap_kind= K " Identifier" )
13561359 else
13571360 # /x ==> (call-pre (error /) x)
13581361 # +₁ x ==> (call-pre (error +₁) x)
13591362 # .<: x ==> (dotcall-pre (error (. <:)) x)
1360- bump_dotted (ps, op_dotted, emit_dot_node= true , remap_kind= K " Identifier" )
1363+ bump_dotted (ps, op_dotted, op_t, emit_dot_node= true , remap_kind= K " Identifier" )
13611364 op_pos = emit (ps, mark, K " error" , error= " not a unary operator" )
13621365 end
13631366 parse_unary (ps)
@@ -1388,7 +1391,7 @@ end
13881391function parse_factor_with_initial_ex (ps:: ParseState , mark)
13891392 parse_decl_with_initial_ex (ps, mark)
13901393 if ((isdot, t) = peek_dotted_op_token (ps); is_prec_power (kind (t)))
1391- bump_dotted (ps, isdot, remap_kind= K " Identifier" )
1394+ bump_dotted (ps, isdot, t, remap_kind= K " Identifier" )
13921395 parse_factor_after (ps)
13931396 emit (ps, mark, isdot ? K " dotcall" : K " call" , INFIX_FLAG)
13941397 end
@@ -2452,11 +2455,11 @@ function parse_import_atsym(ps::ParseState, allow_quotes=true)
24522455 end
24532456 end
24542457 b = peek_behind (ps, pos)
2455- if warn_parens && b. orig_kind != K ".. "
2458+ if warn_parens && b. kind != K "dots "
24562459 emit_diagnostic (ps, mark, warning= " parentheses are not required here" )
24572460 end
24582461 ok = (b. is_leaf && (b. kind == K " Identifier" || is_operator (b. kind))) ||
2459- (! b. is_leaf && b. kind in KSet " $ var" )
2462+ (! b. is_leaf && ( b. kind in KSet " $ var" || b . kind == K " dots " ) )
24602463 if ! ok
24612464 emit (ps, mark, K " error" , error= " expected identifier" )
24622465 end
@@ -2565,10 +2568,6 @@ function parse_import_path(ps::ParseState)
25652568 end
25662569 if k == K " ."
25672570 bump (ps)
2568- elseif k == K " .."
2569- bump_split (ps, (1 ,K " ." ,EMPTY_FLAGS), (1 ,K " ." ,EMPTY_FLAGS))
2570- elseif k == K " ..."
2571- bump_split (ps, (1 ,K " ." ,EMPTY_FLAGS), (1 ,K " ." ,EMPTY_FLAGS), (1 ,K " ." ,EMPTY_FLAGS))
25722571 else
25732572 break
25742573 end
@@ -2587,6 +2586,17 @@ function parse_import_path(ps::ParseState)
25872586 # import A.⋆.f ==> (import (importpath A ⋆ f))
25882587 next_tok = peek_token (ps, 2 )
25892588 if is_operator (kind (next_tok))
2589+ if kind (next_tok) == K " ." && peek (ps, 3 ) == K " ."
2590+ # Import the .. operator
2591+ # import A... ==> (import (importpath A (dots-2)))
2592+ bump_disallowed_space (ps)
2593+ bump (ps, TRIVIA_FLAG)
2594+ dotmark = position (ps)
2595+ bump (ps, TRIVIA_FLAG)
2596+ bump (ps, TRIVIA_FLAG)
2597+ emit (ps, dotmark, K " dots" , set_numeric_flags (2 ))
2598+ continue
2599+ end
25902600 if preceding_whitespace (t)
25912601 # Whitespace in import path allowed but discouraged
25922602 # import A .== ==> (import (importpath A ==))
@@ -2599,10 +2609,6 @@ function parse_import_path(ps::ParseState)
25992609 end
26002610 bump (ps, TRIVIA_FLAG)
26012611 parse_import_atsym (ps)
2602- elseif k == K " ..."
2603- # Import the .. operator
2604- # import A... ==> (import (importpath A ..))
2605- bump_split (ps, (1 ,K " ." ,TRIVIA_FLAG), (2 ,K " .." ,EMPTY_FLAGS))
26062612 elseif k in KSet " NewlineWs ; , : EndMarker"
26072613 # import A; B ==> (import (importpath A))
26082614 break
@@ -3472,6 +3478,16 @@ function parse_atom(ps::ParseState, check_identifiers=true, has_unary_prefix=fal
34723478 # . ==> (error .)
34733479 emit (ps, mark, K " error" , error= " invalid identifier" )
34743480 end
3481+ elseif kind (leading_tok) == K " ." && peek (ps, 2 ) == K " ." && peek (ps, 3 ) == K " ."
3482+ # ...
3483+ bump (ps, TRIVIA_FLAG)
3484+ bump (ps, TRIVIA_FLAG)
3485+ bump (ps, TRIVIA_FLAG)
3486+ emit (ps, mark, K " dots" , set_numeric_flags (3 ))
3487+ if check_identifiers
3488+ # ... ==> (error ...)
3489+ emit (ps, mark, K " error" , error= " invalid identifier" )
3490+ end
34753491 elseif is_error (leading_kind)
34763492 # Errors for bad tokens are emitted in validate_tokens() rather than
34773493 # here.
@@ -3559,9 +3575,9 @@ function parse_atom(ps::ParseState, check_identifiers=true, has_unary_prefix=fal
35593575@label is_operator
35603576 # + ==> +
35613577 # .+ ==> (. +)
3562- bump_dotted (ps, leading_dot, emit_dot_node= true , remap_kind=
3578+ bump_dotted (ps, leading_dot, leading_tok, emit_dot_node= true , remap_kind=
35633579 is_syntactic_operator (leading_kind) ? leading_kind : K " Identifier" )
3564- if check_identifiers && ! is_valid_identifier (leading_kind)
3580+ if check_identifiers && ! ( is_valid_identifier (leading_kind) || (leading_dot && leading_kind == K " . " ) )
35653581 # += ==> (error (op= +))
35663582 # ? ==> (error ?)
35673583 # .+= ==> (error (. (op= +)))
0 commit comments