अजीब Lexical Syntax संरचनाएं
(justine.lol)- llamafile के लिए नया syntax highlighter बनाने के लिए 42 भाषाओं को संभालने पर पता चला कि साधारण lexing में भी भाषा-विशेष अपवाद और पुरानी syntax बारीकी से छिपी रहती हैं
- implementation में C++ और GNU gperf से keyword lookup को तेज बनाया गया, और string, comment, keyword-केंद्रित processing को
forloop औरswitchआधारित finite state machine से हल किया गया - C के trigraph, JavaScript के
u2028·u2029line terminator, Shell·Perl·Ruby के heredoc, Kotlin·Scala·TypeScript·Swift के string interpolation बार-बार ऐसे मामले के रूप में सामने आए जिन्हें केवल lexing से संभालना मुश्किल है - code lines के आधार पर FORTH 125 lines से Ruby 1042 lines तक फैलता है, और Ruby में
<<operator, heredoc और backquote टकराते हैं, इसलिए parsing के बिना highlighting खास तौर पर कठिन है - llamafile का नया highlighter Windows 10 पर Meta LLaMA 3.2 3B Instruct के साथ demo किया गया और macOS·Linux·FreeBSD·NetBSD पर भी चल सकता है, जिससे यह syntax highlighting न रखने वाले ollama से अलग दिखता है
llamafile highlighter बनाने की वजह
- llamafile के लिए नया syntax highlighter बनाने के लिए एक महीने तक 42 programming languages सीखी गईं
- support की जाने वाली languages हैं Ada, Assembly, BASIC, C, C#, C++, COBOL, CSS, D, FORTH, FORTRAN, Go, Haskell, HTML, Java, JavaScript, Julia, JSON, Kotlin, ld, LISP, Lua, m4, Make, Markdown, MATLAB, Pascal, Perl, PHP, Python, R, Ruby, Rust, Scala, Shell, SQL, Swift, Tcl, TeX, TXT, TypeScript, Zig
- यह list TIOBE Index के अधिकांश हिस्से को cover करती है, लेकिन Scratch text के बजाय blocks इस्तेमाल करता है, इसलिए उसे highlighting target से बाहर रखा गया
implementation का तरीका: gperf और finite state machine
- basic syntax highlighter में सबसे बड़ा bottleneck वह जगह है जहां token के keyword होने की पहचान करते समय repeated string comparisons बढ़ जाते हैं
- C++ और GNU gperf का उपयोग करके perfect hash table generate किया गया
- उदाहरण
gperfinputtrue,false,nullजैसे Java constants को keywords के रूप में define करता है gperfसे generated C file collision-free lookup के लिए ऐसा hash function बना सकती है जो केवल एक character पर विचार करता है
- उदाहरण
- C highlighting में लगभग 4,000 keywords define करने पर भी gperf की वजह से 35 MB/s speed से processing संभव है
- बाकी processing के लिए ज्यादातर finite state machine काफी है
flex,bison,ragelके बिना सिर्फforloop औरswitchसे basic highlighter बनाया जा सकता है- strings, comments, keywords पर focus करने पर आम तौर पर lexing level पर processing हो जाती है
- C function names जैसे elements को भी highlight करना हो तो actual parsing की जरूरत पड़ सकती है
- highlight_ada.cpp को example implementation के रूप में इस्तेमाल किया गया
llamafile demo और runtime environment
- नए highlighter और chatbot interface ने llamafile की usability बढ़ाई, और ollama में न होने वाली syntax highlighting differentiator बनी
- demo Windows 10 पर Meta LLaMA 3.2 3B Instruct model के साथ चलाया गया
- यह llamafile macOS, Linux, FreeBSD, NetBSD पर भी चल सकता है
- gemma 27b it जैसे open weight models की quality बेहतर होने से Claude इस्तेमाल करने की प्रेरणा कम होती है
C: सरल भाषा वाली छवि से अलग lexing exceptions
- C को सरल माना जाता है, लेकिन उसके lexical elements काफी unusual हैं
- trigraph
#,[,\,^,{,|,},~जैसे characters को??=,??(,??/,??),??',??<,??!,??>,??-से replace कर सकता है- C23 standard से हटाया गया है, लेकिन legacy software की वजह से compilers इसे support करते रहेंगे, ऐसा लगता है
- अच्छे syntax highlighter को इस syntax को भी handle करना चाहिए
- C का universal character
int \uFEB2 = 1;की तरह ASCII source code में Unicode identifiers को व्यक्त कर सकता है- GCC error देता है अगर वह standards committee द्वारा allow किए गए specific Unicode plane में न हो
- C का single-line comment line-end backslash का उपयोग करने पर कई lines तक फैल सकता है
- Perl, Ruby, Shell जैसी languages जो source code में backslash escape allow करती हैं, वे भी यह C-style behavior support नहीं करतीं
- Tcl और GNU Make इस behavior को support करते हैं, ऐसा समझा गया
- Emacs और Pygments कभी-कभी इसे गलत handle करते हैं, और Vim backslash handling हमेशा सही करता दिखता है
- C में null preprocessor directive भी है
- शुरुआती v6 source code की
.cfiles अक्सर#की एक line से शुरू होती थीं - यह आज भी valid code है, और
cc -C -Eसे comments preserve करने का request करने पर भी preprocessor से कुछ comments हटवाने के लिए इस्तेमाल किया जा सकता है
- शुरुआती v6 source code की
comment syntax: Haskell और D
- C में multi-line comment के अंदर फिर से multi-line comment nest नहीं किया जा सकता
- Haskell
{- ... {- ... -} ... -}form में nested comments support करता है - D ने C के
//,/* ... */comments वैसे ही अपनाए हैं, और अलग से/+ ... +/form की recursive comment syntax introduce की है - D की lexical syntax documentation formal और detailed है, इसलिए implementation के लिए जरूरी जानकारी अच्छी तरह देती है
- D lexical syntax documentation hex strings और heredoc strings जैसी details cover करती है
- D में
"...", backtick strings,r"...",q"...",x"..."आदि कई string forms हैं
Tcl और JavaScript: quotes और अदृश्य line terminators
- Tcl में identifiers के अंदर quotes आ सकते हैं
puts a"ba"bprint करता है- variable names में भी quotes रखे जा सकते हैं, लेकिन reference करते समय
$a"bनहीं बल्कि${a"b}notation इस्तेमाल करना होता है
- JavaScript में regular expressions के लिए built-in lexical syntax है
/[/]/gकी तरह character set brackets के अंदर/को escape करने की जरूरत नहीं होती- सिर्फ closing slash को scan करने वाला simple तरीका minified code में गलत हो सकता है
- ECMAScript
u2028LINE SEPARATOR औरu2029PARAGRAPH SEPARATOR को line terminators के रूप में define करता है- ये characters असल में
\nकी तरह behave करते हैं - ये Trojan Source characters हैं, इसलिए Emacs में इन्हें क्रमशः
↵,¶के रूप में दिखाने की setting की जाती है - कई software इन्हें पहचान नहीं पाते और question mark की तरह render कर देते हैं
- D को छोड़कर ऐसे processing वाली किसी अन्य language की जानकारी नहीं है, ऐसा कहा गया
- ये characters असल में
- इस characteristic का उपयोग करके SectorLISP में C और JavaScript polyglot बनाया जा सका
- lisp.js browser में चलता है और GCC से compile करके local पर भी चलाया जा सकता है
- llamafile ऐसे code को सही highlight करता है, लेकिन अन्य highlighters में वही processing नहीं मिली, ऐसा कहा गया
Shell और heredoc के edge cases
- Shell का heredoc
cat <<EOF ... EOFform में multi-line string लिखता है - quoted heredoc syntax
cat <<'END'variable substitution को disable करती है - heredoc marker को empty string रखने पर अगली empty line पर heredoc खत्म हो जाता है
- example program
helloऔरworldको दो lines में print करता है
- example program
- Shell, Ruby, Perl जैसी heredoc support करने वाली languages में एक ही line पर कई heredoc रखे जा सकते हैं
- Shell में Tcl की तरह
#हमेशा comment शुरू नहीं करता${x#hi-}में#prefix हटाने के लिए इस्तेमाल होता है, और examplethereprint करता है
string interpolation: जिन languages में state stack चाहिए
- Kotlin string
"से शुरू हुई हो तब भी string interpolation की वजह से{पर किसी दूसरे state में जा सकती है - TypeScript, Swift, Kotlin, Scala strings के अंदर actual code डालने की दिशा में string interpolation को मजबूती से support करते हैं
- Kotlin, Scala, TypeScript को highlight करने के लिए braces गिनने और parser state stack maintain करने की जरूरत होती है
- TypeScript अपेक्षाकृत simple है, finite state machine में कुछ states जोड़ने से काम चल जाता है
- Kotlin और Scala double quote और triple quote syntax दोनों में interpolation support करते हैं, इसलिए सिर्फ string lexing के लिए लगभग 13 independent states चाहिए थे
- Swift
"\(var)"interpolation syntax और triple quote support करता है, लेकिन implementation के लिए 10 states चाहिए थे
Swift, C#, FORTH: strings को wrap करने के तरीकों का फर्क
- Swift
"...","""...""",/regex/strings को मनचाही संख्या के#से wrap करने की syntax support करता है- दोनों तरफ
#की संख्या match करनी होती है - यह तरीका string के अंदर quotes या regex boundaries डालने की समस्या हल करता है
- दोनों तरफ
- C# Python की triple quote multi-line strings जैसा है, लेकिन start और end पर match करते हुए अधिक संख्या में quotes इस्तेमाल किए जा सकते हैं
- left side पर रखी quote count right-side termination condition बनती है
- arbitrary number of quotes allow करने पर classic Python triple quote की तुलना में validity rules कम होते हैं, इसलिए finite state machine से decode करना simpler हो सकता है, ऐसा माना गया
- FORTH whitespace boundaries से हर चीज tokenize करता है
- string start syntax
c"भी एक token है c" hello world"का अर्थ अन्य languages के"hello world"जैसा है
- string start syntax
FORTRAN और COBOL: fixed column rules
- llamafile को FORTRAN और COBOL programmers के retire होने के बाद भी banking systems की maintenance में मददगार use case के रूप में पेश किया गया
- air-gapped environment में controllable AI Gemma 27b से COBOL और FORTRAN code request किया जा सकता है, ऐसा कहा गया
- FORTRAN के fixed column rules ये हैं
- column 1 में
*,c,Cरखने पर वह line comment बन जाती है - column 6 में non-space character रखने पर 80 characters से लंबी line continue की जा सकती है
- columns 1~5 में numbers रखने पर वे label बनते हैं
- column 1 में
- COBOL के rules ये हैं
- column 7 में
*रखने पर comment बनता है - column 7 में
-रखने पर 80 characters से लंबी line continue की जा सकती है - columns 1~6 में line number आता है
- column 7 में
Zig और Lua: multi-line strings के अलग समाधान
- Zig में दो backslashes से शुरू होने वाली multi-line string syntax है
- यह syntax Python triple quote strings में
textwrap.dedent()call करने की जरूरत खत्म करती है - downside के रूप में semicolon देखने में अच्छा नहीं लगता, ऐसा माना गया
- Go, Scala, Python जैसी semicolon की जरूरत न रखने वाली languages के लिए विचार करने योग्य string syntax के रूप में propose किया गया
- यह syntax Python triple quote strings में
- Lua की multi-line string
[[...]]पर आधारित है, और brackets के बीच मनचाही संख्या में=डाले जा सकते हैं[==[ ... ]==]की तरह start और end में=की count match की जाती है- comment में भी वही तरीका इस्तेमाल किया जा सकता है
--[[ ... ]]और--[==[ ... ]==]दोनों forms संभव हैं
Assembly: dialects और preprocessors का combination
- Assembly कई dialects में बंटी हुई है, इसलिए highlight करना कठिन languages में से एक है
- llamafile का लक्ष्य AT&T, nasm आदि कई syntaxes को reasonable तरीके से handle करना है
- keywords को line में पहले identifier और colon के बाद न आने वाले item के रूप में handle करें तो अधिकांश assembly code ठीक-ठाक दिख सकता है
- comment syntax भी simple नहीं है
- original UNIX comment के लिए केवल single
/चाहिए था - GNU as अभी भी line start position पर ही इस comment को support करता है
- Clang fixed comment support नहीं करता, इसलिए open-source code में practically इस्तेमाल करना कठिन है, ऐसा कहा गया
- original UNIX comment के लिए केवल single
- original UNIX assembler character literals में closing quote नहीं लगाता था
'xcharacterxके value0x78को दर्शाता है- GNU as इसे अब भी support करता है लेकिन LLVM support नहीं करता
- existing code में यह syntax है, इसलिए अच्छे highlighter को support करना चाहिए
- GNU assembler quoted identifiers allow करता है, जिससे symbols में लगभग कोई भी character रखा जा सकता है
- Assembly अक्सर C preprocessor या m4 के साथ इस्तेमाल होती है
dnl,m4_dnl,Cसे शुरू होने वाली lines को भी comments के रूप में handle करना चाहिए
Ada और BASIC: छोटी syntax से lexing हिलने के उदाहरण
- Ada को lex करना काफी simple है, लेकिन single quote का उपयोग unusual है
- C की तरह
'x'character literal हो सकता है Foo'Sizeकी तरह attributes reference करते समय भी single quote इस्तेमाल होता हैCharacter'(')')'Imagecharacter declare करता है औरImagefunction के जरिए string representation में convert करता है
- C की तरह
- Commodore BASIC example syntax highlighting की कई assumptions तोड़ता है
- strings line end पर closing quote छोड़ सकती हैं
- variable names में
$जैसे sigil लगते हैं gotoजैसे keywords identifiers के अंदर भी aggressively lex किए जाते हैं
- Visual BASIC में
#1/1/2024#जैसी date literal syntax है - Visual BASIC में
#If DEBUG Then,#Else,#End Ifजैसे preprocessor directives भी हैं, इसलिए lexing tricky है
Perl: Shell और programming language के बीच की complexity
- Perl Shell और programming language के बीच है, इसलिए दोनों तरफ की complexities विरासत में मिलती हैं
- इसने regular expressions को language का first-class element बनाया, और उसका असर Python जैसी अन्य languages तक पहुंचा
- Perl की substitution syntax
s/hello/Perl/iकी तरह sed जैसी है/की जगह कोई भी punctuation character delimiter के रूप में इस्तेमाल किया जा सकता हैs!hello!Perl!iतब सुविधाजनक है जब slash regex में होs{hello}{Perl}iकी तरह paired characters इस्तेमाल करने पर additional character की जरूरत होती है
- Perl में strings की तरह highlight किए जाने वाले कई magic prefixes हैं
m,s,y,qr,qw,qq,qxआदि अलग-अलग delimiters के साथ इस्तेमाल होते हैं
y/x/y/को division समझ लेने से बचने के लिए context देखना पड़ता है- Perl variables में scalar
$, array@, hash%जैसे sigils होते हैं, इसलिए पूरी syntax parse किए बिना भी distinguish करने में मदद मिलती है
- Perl variables में scalar
- Perl source code में man page के लिए POD documentation रखने की convention है
- line start का
=wordPOD documentation शुरू करता है और=cutउसे खत्म करता है
- line start का
Ruby: lexing का सबसे कठिन target
- Ruby पिछले languages के union जैसी दिखती है, और syntax formal रूप से पर्याप्त document नहीं है, ऐसा आकलन है
- Ruby manual का syntax document details में हल्का माना गया
- Ruby backquote syntax support करती है और साथ ही backquote को method name की तरह इस्तेमाल कर सकती है, इसलिए highlighter के लिए यह तय करना कठिन है कि यह string है या नहीं
- Ruby में
<<operator और heredoc दोनों हैं- real code में
options[:includes] <<arg; trueजैसी form मौजूद है - यह code heredoc जैसा दिख सकता है, और Emacs भी इसे गलत handle करता है
- real code में
puts "This is #{<<HERE.strip} evil"जैसी string interpolation के अंदर heredoc वाला code भी valid है- 42 languages में Ruby को सबसे बड़ा shock माना गया, और Ruby को parsing के बिना lex करना संभव न हो सकता है; parsing के बाद भी interpretability का भरोसा करना मुश्किल है, ऐसा माना गया
implementation code line count से देखी गई complexity
- हर language highlighter implementation की code line count के आधार पर FORTH सबसे simple और Ruby सबसे complex है
- सबसे छोटा implementation highlight_forth.cpp 125 lines का है
- अपेक्षाकृत छोटे implementations में m4 132 lines, Ada 149 lines, LISP 160 lines, MATLAB 166 lines, COBOL 186 lines, BASIC 199 lines, FORTRAN 200 lines आदि हैं
- medium-size implementations में JavaScript 337 lines, TypeScript 371 lines, Kotlin 387 lines, Scala 387 lines, Assembly 447 lines, C 449 lines, Swift 455 lines, D 521 lines शामिल हैं
- सबसे लंबे implementations Shell 570 lines, Perl 583 lines, highlight_ruby.cpp 1042 lines हैं
1 टिप्पणियां
Hacker News की राय
C trigraphs में मेरा पसंदीदा रूप
do_action() ??!??! handle_error()जैसा हैयह किसी खास error handling syntax जैसा दिखता है, लेकिन असल में
??!??!बदलकर||logical OR बन जाता है, और short-circuit evaluation के नियमों से जबdo_action()non-zero value लौटाता है तोhandle_error()चलाने वाली संरचना बनती है—यह बात संतोषजनक लगती है??!को|में बदला जाता है, इसलिए??!??!||, यानी “or” बन जाता है||की जगह पुराना C trigraph चुना गया था?पढ़ने में मज़ा आया, लेकिन उलटे Lisp वाले नज़रिए से ज्यादा सहमति महसूस हुई
मेरी समझ में इसका रुख यह है कि syntax भाषा का बहुत अहम हिस्सा नहीं है, और मदद से ज्यादा बाधा बनने की संभावना रखता है, इसलिए उसे जितना हो सके सरल और समानरूप होना चाहिए ताकि बाकी चीज़ों पर ध्यान दिया जा सके
हालांकि Lisp में structural editing सीखना अब तक मदद से ज्यादा बाधा जैसा रहा है, और लगता है कि शायद कभी आगे इसका फल मिलेगा
Lisp की तरह सरल बनाने पर syntax की चर्चा बस semantics की समस्या में खिसक जाती है, यानी परत ही बदलती है
मेरे हिसाब से जटिल semantics वाले सरल syntax की तुलना में जटिल syntax पढ़ना और लिखना कहीं आसान है। syntax errors पर जल्दी feedback मिल जाता है, लेकिन semantic errors रनटाइम तक छिपे रह सकते हैं
उदाहरण के लिए https://pyret.org/ जैसी चीज़ भी है। असल में Lisp को सरल या अनिवार्य रूप से uniform मानना मुश्किल है
parinferइस्तेमाल करें और बसslurp,barf,raiseइन तीन commands की key bindings जान लेंइन चार चीज़ों से ही paredit के फायदे बिना जटिलता के लगभग 95% मिल जाते हैं, और बाकी तरकीबें आदत पड़ने के बाद सीखी जा सकती हैं
एक हिस्सा था, “पता नहीं कौन C को 35MB प्रति सेकंड पर syntax highlight करना चाहता है, लेकिन अब यह संभव है”; यह तेज़ तो है, लेकिन
tccबहुत पुराने कंप्यूटरों पर भी C को binary code में 29MB प्रति सेकंड compile करता है: https://bellard.org/tcc/#speedइससे तेज़ भी संभव होगा, लेकिन शायद जरूरत नहीं पड़ेगी
लेखक ने कुछ बातें छोड़ दी हैं
TypeScript, Swift, Kotlin, Scala ही वे भाषाएँ नहीं हैं जो string interpolation में असली code डालने की हद तक गई हैं; C#, Python, JavaScript, Ruby, Shell, Make भी कुछ ऐसा ही सपोर्ट करते हैं
Tcl में code और data को अलग करना मुश्किल है, इसलिए
{ }असल में एक अजीब string delimiter जैसा है, औरxyzzy {#hello world}में#hello worldcomment है या string, यह evaluation के समय से पहले पता नहीं चल सकताPostgreSQL में सुविधाजनक dollar-quoted strings हैं, इसलिए https://www.postgresql.org/docs/current/sql-syntax-lexical.h... की तरह
'Dianne''s horse',$$Dianne's horse$$,$SomeTag$Dianne's horse$SomeTag$का अर्थ समान होता है"I have $foo $bar's: @{[$bar x $foo]}"जैसी stringI have 5 x's: xxxxxoutput कर सकती है@{[...]}syntax Perl की उस विशेषता का उपयोग करता है जिसमें scalar के साथ-साथ array interpolation भी संभव है; अंदर वाला[...]array reference बनाता है और बाहर वाला@{...}उसे dereference करता है। Perl interpreter उस अंदरूनी expression में arbitrary code की अनुमति देता हैतब
"foo { toUpper("bar { x + y } bar") } foo"की तरह nesting की जा सकती है, और अगर+string concatenation है तो यह असल में"foo " + toUpper("bar " + (x + y) + " bar") + " foo"के बराबर हो जाता हैपता नहीं कोई भाषा सच में ऐसे काम करती है या नहीं
मुझे Ruby पसंद है, लेकिन string interpolation और heredoc मिलाकर बना
puts "This is #{<जैसा valid Ruby बचाव करना कठिन हैसाथ ही Ruby में whitespace भी quote character हो सकता है। ऐसे context में जहाँ left operand नहीं है,
%quoted string शुरू करता है और अगला character quote की किस्म बताता है, इसलिए% hellohelloरखने वाली string बन जाता है।%(this is a string)या%{this is a string}अच्छे हैं, लेकिन whitespace का इस्तेमाल मैंने असल दुनिया में कभी नहीं देखा, औरirbभी उसे ठीक से handle नहीं करता, इसलिए इसे हटाया जाए तो अच्छा होगाval s"${a} + ${b}" = "1 + 2"लिखने परa1औरb2हो जाते हैंपहले hot loops में
log.trace($"Entering iteration {i} for customer {c.ID} [{c.ShortName}]");जैसा code logger के बाहर निकलने से पहले भी हर बारstring.Concatcall करता था, इसलिए कई loggers ने अपना interpolation लागू कियाC# में
DefaultInterpolatedStringHandlerया custom handler pattern लेने वाले overloads declare किए जा सकते हैं, और यह overload प्राथमिकता पाकर पहले जांच सकता है कि वास्तविक log की जरूरत है या नहीं, फिर string creation को टाल सकता हैयहां ज़िक्र न की गई एक और grammar की विचित्रता है, जो ज़्यादातर syntax highlighter तोड़ देती है
Java में Unicode escape सिर्फ़ string के अंदर नहीं, बल्कि कहीं भी आ सकता है
उदाहरण के लिए
class Foo\u007b}एक valid class है, और//comment के अंदर\u000Aको असली newline की तरह process किया जा सकता है, इसलिएassertवाला उदाहरण भी उम्मीद से अलग व्यवहार करता हैUnicode escape से block comment को ख़त्म किया जा सकता है, इसलिए Java source file में comment के अंदर malicious code छिपाना हो तो बस comment में Unicode escape block होने का कोई बहाना बनाना काफ़ी है
जो developer इस feature को नहीं जानता, वह इसे commented-out समझकर शायद आगे बढ़ जाएगा
“Ruby ऐसी भाषा है जो syntax समझने की हर कोशिश से बच निकलती है” वाला हिस्सा है, लेकिन मनमाने ढंग से reprogrammable lexer रखने वाले TeX के नज़रिए से यह प्यारा-सा स्तर है
“हर C programmer जानता है कि multi-line comment के अंदर multi-line comment नहीं डाला जा सकता”, लेकिन Standard ML programmer के लिए यह एक अप्रत्याशित सीमा हो सकती है
(* (* Nested (**) *) comment *)जैसी nested comment valid है, और उसके बादval _ = print "hello, world\n"भी सामान्य रूप से execute होता हैयह सोचें कि C के आने के समय उसे expressive language माना जाता था, तो nested comment का language में शामिल न होना दिलचस्प है
ML में single-line comment नहीं था, इसलिए वह भी इसी तरह हैरान करने वाली सीमा है, और C को “expressive” कहना पहली बार सुन रहा हूं, लेकिन 1972 में assembly से तुलना करें तो शायद ऐसा रहा हो
और comment syntax का language की expressiveness से क्या संबंध है, यह मुझे समझ नहीं आता; परिभाषा के हिसाब से तो बिल्कुल नहीं है
परंपरागत रूप से lexical analysis को regular expression जैसी finite state automaton तक सीमित क्षेत्र माना जाता था, इसलिए ऐसी capability lexing के दायरे से बाहर लगती थी
#if 0इस्तेमाल करें तो comment nest करने का एक तरीका है#if 0 ... #if 0 ... #endif ... #endifकी तरह wrap कर सकते हैंjoe की syntax highlighting implementation को reusable रूप में देखना चाहूंगा
https://joe-editor.sf.net/ का format Python f-string को ठीक से highlight कर पाने जितना शक्तिशाली है
संबंधित documentation और examples https://github.com/cmur2/joe-syntax/blob/joe-4.4/misc/HowItW..., https://gist.github.com/irdc/6188f11b1e699d615ce2520f03f1d0d... पर हैं
state और transition grammar standard tools की तुलना में कहीं ज़्यादा समझने में आसान थे
कमी यह है कि rule set लंबा-चौड़ा हो जाता है और ideal structuring थोड़ी मुश्किल हो जाती है, लेकिन code से सभी production rules infer करना आसान हो जाता है, इस मायने में मैं इसे उल्टा एक फायदा मानता हूं
लगता है लेखक ने TeX syntax highlighting की कोशिश नहीं की है
mental health के लिए यह अच्छा हो सकता है, क्योंकि TeX में आम तौर पर interpret किए बिना complete syntax highlighting संभव नहीं होती
सिर्फ़ parsing भी काफ़ी नहीं है, क्योंकि हर character का काम redefine किया जा सकता है, यानी “अब K
{है और C}है” जैसी हरकत भी संभव हैअसल में arXiv papers में भी कुछ ऐसे हैं जो इस cursed feature का इस्तेमाल करते हैं
.texfiles पर यह टूटे बिना काफ़ी अच्छी highlighting करता हैलक्ष्य real-world usage का 99.9% cover करना है। ऐसा होने पर LLM से निकलने वाली चीज़ें भी आम तौर पर cover हो जाने की संभावना है
obscure syntax भी आम तौर पर बड़ी समस्या नहीं बनता, जब तक कि कोई string या comment file के अंत तक फैलकर बाकी source code को ढक न दे
\makeatletterका मतलब “किसी चीज़ को at character बनाना” नहीं, बल्कि parsing करते समय@character को letter की तरह treat करना हैमेरे हिसाब से Vim जैसा अच्छा syntax highlighting engine लिखना आसान नहीं है
syntax highlighting में context processing की ज़रूरत होती है, जहाँ किसी खास तरीके से nested content पर अलग-अलग rules लागू होते हैं
Vim syntax highlighter आपको
matchऔरregionनाम के दो तरह के items declare करने देता है;matchएक simple lexical rule है, जबकिregionके पास start, end और middle को अलग-अलग match करने वाली expressions होती हैंitems को इस तरह declare किया जा सकता है कि वे केवल किसी खास region के अंदर होने पर ही active हों, और inclusion relationships भी आपस में declare किए जा सकते हैं
इस basic semantic structure के ऊपर कई special cases के लिए features जोड़े गए हैं। Justine भी शायद interview में तुरंत इसे नहीं बना पाएंगी; यह कम से कम एक overnight assignment जैसा काम होगा
manpage HTML conversion result लेकर उसे TXR manual HTML में refine करने वाली
genmanscript यहाँ है: https://www.kylheku.com/cgit/txr/tree/genman.txrजो हिस्सा white दिखता है वह literal template है, और Lisp code
@(do ...)जैसे directives के अंदर आता है। TXR keywords purple रंग में, TXR Lisp keywords green रंग में दिखते हैं, और वही शब्द context के हिसाब से अलग हो सकता हैquasi-strings भी nested grammar रख सकती हैं, और उनके अंदर फिर embedded code या quasi-strings आ सकती हैं।
txr.vimऔरtl.vimsyntax definition files दोनों https://www.kylheku.com/cgit/txr/tree/genvim.txr से generate होती हैंअगर ऐसा नहीं किया जाता, तो शायद efficiency की वजह से होगा। उदाहरण के लिए, सिर्फ screen पर दिख रहे हिस्से को highlight करने के बजाय पूरी file parse करनी पड़े, तो cost काफी बढ़ सकती है