From 21c67740c93f5a04008232d0f638c830a0852ba9 Mon Sep 17 00:00:00 2001 From: Claire Foster Date: Wed, 31 Jul 2024 11:34:01 +1000 Subject: [PATCH] =?UTF-8?q?Allow=20any=20of=20`=E2=89=94=20=E2=A9=B4=20?= =?UTF-8?q?=E2=89=95`=20as=20identifiers=20(#478)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These assignment-precedence operators shouldn't be special syntax and should instead be usable as normal identifiers just like `~`. Also add more test cases for the true syntactic operators. Fixes #405 --- src/kinds.jl | 5 ++++- src/parser.jl | 5 +++-- test/parser.jl | 28 ++++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/kinds.jl b/src/kinds.jl index 8aa8a9b2..800d9622 100644 --- a/src/kinds.jl +++ b/src/kinds.jl @@ -298,6 +298,7 @@ register_kinds!(JuliaSyntax, 0, [ # Level 1 "BEGIN_ASSIGNMENTS" + "BEGIN_SYNTACTIC_ASSIGNMENTS" "=" "+=" "-=" # Also used for "−=" @@ -314,9 +315,10 @@ register_kinds!(JuliaSyntax, 0, [ "\\=" "&=" ":=" - "~" "\$=" "⊻=" + "END_SYNTACTIC_ASSIGNMENTS" + "~" "≔" "⩴" "≕" @@ -1227,6 +1229,7 @@ is_prec_pipe_lt(x) = kind(x) == K"<|" is_prec_pipe_gt(x) = kind(x) == K"|>" is_syntax_kind(x) = K"BEGIN_SYNTAX_KINDS"<= kind(x) <= K"END_SYNTAX_KINDS" is_macro_name(x) = K"BEGIN_MACRO_NAMES" <= kind(x) <= K"END_MACRO_NAMES" +is_syntactic_assignment(x) = K"BEGIN_SYNTACTIC_ASSIGNMENTS" <= kind(x) <= K"END_SYNTACTIC_ASSIGNMENTS" function is_number(x) kind(x) in (K"Integer", K"BinInt", K"HexInt", K"OctInt", K"Float", K"Float32") diff --git a/src/parser.jl b/src/parser.jl index 94a7b8da..2287e8aa 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -279,7 +279,7 @@ function is_syntactic_operator(k) # TODO: Do we need to disallow dotted and suffixed forms here? # The lexer itself usually disallows such tokens, so it's not clear whether # we need to handle them. (Though note `.->` is a token...) - return k in KSet"&& || . ... ->" || (is_prec_assignment(k) && k != K"~") + return k in KSet"&& || . ... ->" || is_syntactic_assignment(k) end function is_syntactic_unary_op(k) @@ -617,7 +617,8 @@ function parse_assignment_with_initial_ex(ps::ParseState, mark, down::T) where { # [a ~b] ==> (hcat a (call-pre ~ b)) return end - # ~ is the only non-syntactic assignment-precedence operator. + # ~ is currently the only assignment-precedence operator which is parsed as a call. + # TODO: Make the other non-syntactic assignments such as `≔ ⩴ ≕` into calls as well? # a ~ b ==> (call-i a ~ b) # a .~ b ==> (dotcall-i a ~ b) # [a ~ b c] ==> (hcat (call-i a ~ b) c) diff --git a/test/parser.jl b/test/parser.jl index b7b7839d..d69811ad 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -763,12 +763,36 @@ tests = [ """var"x"1""" => "(var x (error-t))" """var"x"y""" => "(var x (error-t))" # Standalone syntactic operators are errors - "+=" => "(error +=)" "?" => "(error ?)" + "&&" => "(error &&)" + "||" => "(error ||)" + "." => "(error .)" + "..." => "(error ...)" + "+=" => "(error +=)" + "-=" => "(error -=)" + "*=" => "(error *=)" + "/=" => "(error /=)" + "//=" => "(error //=)" + "|=" => "(error |=)" + "^=" => "(error ^=)" + "÷=" => "(error ÷=)" + "%=" => "(error %=)" + "<<=" => "(error <<=)" + ">>=" => "(error >>=)" + ">>>="=> "(error >>>=)" + "\\=" => "(error \\=)" + "&=" => "(error &=)" + ":=" => "(error :=)" + "\$=" => "(error \$=)" + "⊻=" => "(error ⊻=)" ".+=" => "(error (. +=))" # Normal operators "+" => "+" + # Assignment-precedence operators which can be used as identifiers "~" => "~" + "≔" => "≔" + "⩴" => "⩴" + "≕" => "≕" # Quoted syntactic operators allowed ":+=" => "(quote-: +=)" ":.=" => "(quote-: (. =))" @@ -777,7 +801,7 @@ tests = [ ":end" => "(quote-: end)" ":(end)" => "(quote-: (parens (error-t)))" ":<:" => "(quote-: <:)" - # unexpect = + # unexpected = "=" => "(error =)" # parse_cat "[]" => "(vect)"