From 5644f4186577bf14a870a2840488141973f84d00 Mon Sep 17 00:00:00 2001 From: Hannu Hartikainen Date: Tue, 8 Nov 2022 12:25:43 +0200 Subject: [PATCH] Add lexer for BQN (#691) Based on the Vim syntax highlighting by Marshall Lochbaum[[0]], with number parsing from PrismJS highlighter by Christopher Rodriguez[[1]]. The lexed types are selected to be as descriptive as possible while retaining similar groupings to the Vim highlighter, so the highlighted code looks familiar to BQN users. [0]: https://github.com/mlochbaum/BQN/blob/a436a71a083f410fd58d86e8d228470c68c24b91/editors/vim/syntax/bqn.vim [1]: https://github.com/PrismJS/prism/commit/859f99a042e2f9c072a882b4cf9bf5f1f7804fa9 --- README.md | 2 +- lexers/embedded/bqn.xml | 83 +++++++++++ lexers/testdata/bqn.actual | 31 +++++ lexers/testdata/bqn.expected | 258 +++++++++++++++++++++++++++++++++++ 4 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 lexers/embedded/bqn.xml create mode 100644 lexers/testdata/bqn.actual create mode 100644 lexers/testdata/bqn.expected diff --git a/README.md b/README.md index 3a879a8c3..2fa78bf41 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ translators for Pygments lexers and styles. Prefix | Language :----: | -------- A | ABAP, ABNF, ActionScript, ActionScript 3, Ada, Angular2, ANTLR, ApacheConf, APL, AppleScript, Arduino, Awk -B | Ballerina, Base Makefile, Bash, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, Brainfuck +B | Ballerina, Base Makefile, Bash, Batchfile, BibTeX, Bicep, BlitzBasic, BNF, Brainfuck, BQN C | C, C#, C++, Caddyfile, Caddyfile Directives, Cap'n Proto, Cassandra CQL, Ceylon, CFEngine3, cfstatement, ChaiScript, Chapel, Cheetah, Clojure, CMake, COBOL, CoffeeScript, Common Lisp, Coq, Crystal, CSS, Cython D | D, Dart, Diff, Django/Jinja, Docker, DTD, Dylan E | EBNF, Elixir, Elm, EmacsLisp, Erlang diff --git a/lexers/embedded/bqn.xml b/lexers/embedded/bqn.xml new file mode 100644 index 000000000..c1090ea5a --- /dev/null +++ b/lexers/embedded/bqn.xml @@ -0,0 +1,83 @@ + + + BQN + bqn + *.bqn + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lexers/testdata/bqn.actual b/lexers/testdata/bqn.actual new file mode 100644 index 000000000..064a2d093 --- /dev/null +++ b/lexers/testdata/bqn.actual @@ -0,0 +1,31 @@ +#! /usr/bin/env bqn + +# From BQN documentation / quick start: +# https://mlochbaum.github.io/BQN/doc/quick.html + +# Case conversion utilities +case ← { + diff ← -´ "Aa" + Lower ⇐ -⟜diff + Upper ⇐ Lower⁼ +} + +hw ← <˘ 2‿∘ ⥊ "helloworld" +hw case.Upper⌾(⊑¨)↩ +•Out hw ↩ ∾ ⥊⍉ [hw, ", "‿"!"] # Hello, World! + +# Split at spaces and repeated characters +Split ← { + !1==𝕩 ⋄ (!2=•Type)¨𝕩 + Proc ← { + · 𝕊 ' ': spl⇐1 ; # Space: break and delete it + prev Fn cur: ⟨spl,str⟩⇐ + spl←0 ⋄ str←⟨cur⟩ # Include and don't break... + { prev=cur ? spl+↩1 ; @ } # except at equal characters + } + GV‿GS ← {𝕏¨}¨ ⟨ {⟨s⇐str⟩:s;""} + {𝕩.spl} ⟩ + r ← Proc{»𝔽¨⊢} 𝕩 + (∾¨ GV ⊔˜ ·+`GS) r +} +•Show Split hw # ⟨ "Hel" "lo," "World!" ⟩ diff --git a/lexers/testdata/bqn.expected b/lexers/testdata/bqn.expected new file mode 100644 index 000000000..19ce024a0 --- /dev/null +++ b/lexers/testdata/bqn.expected @@ -0,0 +1,258 @@ +[ + {"type":"CommentPreproc","value":"#! /usr/bin/env bqn"}, + {"type":"TextWhitespace","value":"\n\n"}, + {"type":"CommentSingle","value":"# From BQN documentation / quick start:"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"CommentSingle","value":"# https://mlochbaum.github.io/BQN/doc/quick.html"}, + {"type":"TextWhitespace","value":"\n\n"}, + {"type":"CommentSingle","value":"# Case conversion utilities"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"Name","value":"case"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"Name","value":"diff"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"-"}, + {"type":"Operator","value":"´"}, + {"type":"TextWhitespace","value":" "}, + {"type":"LiteralString","value":"\"Aa\""}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"NameFunction","value":"Lower"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"⇐"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"-"}, + {"type":"OperatorWord","value":"⟜"}, + {"type":"Name","value":"diff"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"NameFunction","value":"Upper"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"⇐"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"Lower"}, + {"type":"Operator","value":"⁼"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":"\n\n"}, + {"type":"Name","value":"hw"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"\u003c"}, + {"type":"Operator","value":"˘"}, + {"type":"TextWhitespace","value":" "}, + {"type":"LiteralNumber","value":"2"}, + {"type":"KeywordPseudo","value":"‿"}, + {"type":"OperatorWord","value":"∘"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"⥊"}, + {"type":"TextWhitespace","value":" "}, + {"type":"LiteralString","value":"\"helloworld\""}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"Name","value":"hw"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"case"}, + {"type":"Text","value":"."}, + {"type":"NameFunction","value":"Upper"}, + {"type":"OperatorWord","value":"⌾"}, + {"type":"Punctuation","value":"("}, + {"type":"NameFunction","value":"⊑"}, + {"type":"Operator","value":"¨"}, + {"type":"Punctuation","value":")"}, + {"type":"Text","value":"↩"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"NameFunction","value":"•Out"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"hw"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"↩"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"∾"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"⥊⍉"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"["}, + {"type":"Name","value":"hw"}, + {"type":"KeywordPseudo","value":","}, + {"type":"TextWhitespace","value":" "}, + {"type":"LiteralString","value":"\", \""}, + {"type":"KeywordPseudo","value":"‿"}, + {"type":"LiteralString","value":"\"!\""}, + {"type":"KeywordPseudo","value":"]"}, + {"type":"TextWhitespace","value":" "}, + {"type":"CommentSingle","value":"# Hello, World!"}, + {"type":"TextWhitespace","value":"\n\n"}, + {"type":"CommentSingle","value":"# Split at spaces and repeated characters"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"NameFunction","value":"Split"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"NameFunction","value":"!"}, + {"type":"LiteralNumber","value":"1"}, + {"type":"NameFunction","value":"=="}, + {"type":"Name","value":"𝕩"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"⋄"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Punctuation","value":"("}, + {"type":"NameFunction","value":"!"}, + {"type":"LiteralNumber","value":"2"}, + {"type":"NameFunction","value":"=•Type"}, + {"type":"Punctuation","value":")"}, + {"type":"Operator","value":"¨"}, + {"type":"Name","value":"𝕩"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"NameFunction","value":"Proc"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"NameConstant","value":"·"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"𝕊"}, + {"type":"TextWhitespace","value":" "}, + {"type":"LiteralStringChar","value":"' '"}, + {"type":"Punctuation","value":":"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"spl"}, + {"type":"Text","value":"⇐"}, + {"type":"LiteralNumber","value":"1"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Punctuation","value":";"}, + {"type":"TextWhitespace","value":" "}, + {"type":"CommentSingle","value":"# Space: break and delete it"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"Name","value":"prev"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"Fn"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"cur"}, + {"type":"Punctuation","value":":"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"⟨"}, + {"type":"Name","value":"spl"}, + {"type":"KeywordPseudo","value":","}, + {"type":"Name","value":"str"}, + {"type":"KeywordPseudo","value":"⟩"}, + {"type":"Text","value":"⇐"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"Name","value":"spl"}, + {"type":"Text","value":"←"}, + {"type":"LiteralNumber","value":"0"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"⋄"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"str"}, + {"type":"Text","value":"←"}, + {"type":"KeywordPseudo","value":"⟨"}, + {"type":"Name","value":"cur"}, + {"type":"KeywordPseudo","value":"⟩"}, + {"type":"TextWhitespace","value":" "}, + {"type":"CommentSingle","value":"# Include and don't break..."}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"prev"}, + {"type":"NameFunction","value":"="}, + {"type":"Name","value":"cur"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Punctuation","value":"?"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"spl"}, + {"type":"NameFunction","value":"+"}, + {"type":"Text","value":"↩"}, + {"type":"LiteralNumber","value":"1"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Punctuation","value":";"}, + {"type":"TextWhitespace","value":" "}, + {"type":"LiteralStringChar","value":"@"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":" "}, + {"type":"CommentSingle","value":"# except at equal characters"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"NameFunction","value":"GV"}, + {"type":"KeywordPseudo","value":"‿"}, + {"type":"NameFunction","value":"GS"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"NameFunction","value":"𝕏"}, + {"type":"Operator","value":"¨"}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"Operator","value":"¨"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"⟨"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"{⟨"}, + {"type":"Name","value":"s"}, + {"type":"Text","value":"⇐"}, + {"type":"Name","value":"str"}, + {"type":"KeywordPseudo","value":"⟩"}, + {"type":"Punctuation","value":":"}, + {"type":"Name","value":"s"}, + {"type":"Punctuation","value":";"}, + {"type":"LiteralString","value":"\"\""}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"Name","value":"𝕩"}, + {"type":"Text","value":"."}, + {"type":"Name","value":"spl"}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":" "}, + {"type":"KeywordPseudo","value":"⟩"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"Name","value":"r"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Text","value":"←"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"Proc"}, + {"type":"KeywordPseudo","value":"{"}, + {"type":"NameFunction","value":"»𝔽"}, + {"type":"Operator","value":"¨"}, + {"type":"NameFunction","value":"⊢"}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"𝕩"}, + {"type":"TextWhitespace","value":"\n "}, + {"type":"Punctuation","value":"("}, + {"type":"NameFunction","value":"∾"}, + {"type":"Operator","value":"¨"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"GV"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"⊔"}, + {"type":"Operator","value":"˜"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameConstant","value":"·"}, + {"type":"NameFunction","value":"+"}, + {"type":"Operator","value":"`"}, + {"type":"NameFunction","value":"GS"}, + {"type":"Punctuation","value":")"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"r"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"KeywordPseudo","value":"}"}, + {"type":"TextWhitespace","value":"\n"}, + {"type":"NameFunction","value":"•Show"}, + {"type":"TextWhitespace","value":" "}, + {"type":"NameFunction","value":"Split"}, + {"type":"TextWhitespace","value":" "}, + {"type":"Name","value":"hw"}, + {"type":"TextWhitespace","value":" "}, + {"type":"CommentSingle","value":"# ⟨ \"Hel\" \"lo,\" \"World!\" ⟩"}, + {"type":"TextWhitespace","value":"\n"} +]