From 0fa16dc46fd2dba2820595fd1eea25b271b7a74f Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 15 Sep 2023 13:57:44 -0400 Subject: Add first pass at a JavaScript lexer. --- Makefile.am | 1 + syntax-highlight/javascript.scm | 74 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 syntax-highlight/javascript.scm diff --git a/Makefile.am b/Makefile.am index 191f12b..e059e0f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,7 @@ SOURCES = \ syntax-highlight/c.scm \ syntax-highlight/css.scm \ syntax-highlight/gitignore.scm \ + syntax-highlight/javascript.scm \ syntax-highlight/lisp.scm \ syntax-highlight/scheme.scm \ syntax-highlight/xml.scm \ diff --git a/syntax-highlight/javascript.scm b/syntax-highlight/javascript.scm new file mode 100644 index 0000000..544c213 --- /dev/null +++ b/syntax-highlight/javascript.scm @@ -0,0 +1,74 @@ +;;; guile-syntax-highlight --- General-purpose syntax highlighter +;;; Copyright © 2023 David Thompson +;;; +;;; Guile-syntax-highlight is free software; you can redistribute it +;;; and/or modify it under the terms of the GNU Lesser General Public +;;; License as published by the Free Software Foundation; either +;;; version 3 of the License, or (at your option) any later version. +;;; +;;; Guile-syntax-highlight is distributed in the hope that it will be +;;; useful, but WITHOUT ANY WARRANTY; without even the implied +;;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +;;; See the GNU Lesser General Public License for more details. +;;; +;;; You should have received a copy of the GNU Lesser General Public +;;; License along with guile-syntax-highlight. If not, see +;;; . + +;;; Commentary: +;; +;; Syntax highlighting for JavaScript. +;; +;;; Code: + +(define-module (syntax-highlight javascript) + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) + #:use-module (syntax-highlight lexers) + #:export (lex-javascript)) + +(define %js-reserved-words + '("async" "await" "break" "case" "catch" "class" "const" "continue" + "debugger" "default" "delete" "do" "else" "export" "extends" "false" + "finally" "for" "function" "if" "import" "in" "instanceof" "let" "new" + "null" "return" "static" "super" "switch" "this" "throw" "true" "try" + "typeof" "var" "void" "while" "with" "yield")) + +(define (js-reserved-word? str) + (any (cut string=? <> str) %js-reserved-words)) + +(define %js-operators + '(";" "," "." "?." "..." "#" "=" "+=" "-=" "*=" "/=" "%=" "<<=" ">>=" + ">>>=" "&=" "^=" "|=" "**=" "&&=" "||=" "??=" "?" ":" "||" "&&" "??" + "|" "^" "&" "~" "==" "===" "!=" "!==" "<=" ">=" "<" ">" "<<" ">>" ">>>" + "*" "/" "%" "!" "++" "--" "+" "-" )) + +(define lex-js-operator + (lex-any* (map lex-string %js-operators))) + +;; A rough approximation of characters that are allowed in Javascript +;; variables, numbers, etc. +(define char-set:js-identifier + (char-set-adjoin char-set:letter+digit #\$ #\_)) + +(define lex-js-identifier + (lex-char-set char-set:js-identifier)) + +;; TODO: Highlight regexp literals. +(define lex-javascript + (lex-consume + (lex-any (lex-char-set char-set:whitespace) + (lex-tag 'open (lex-any* (map lex-string '("(" "[" "{")))) + (lex-tag 'close (lex-any* (map lex-string '(")" "]" "}")))) + (lex-tag 'comment (lex-any (lex-delimited "//" #:until "\n") + (lex-delimited "/*" #:until "*/") + (lex-delimited "#!" #:until "\n"))) + (lex-tag 'special (lex-filter js-reserved-word? lex-js-identifier)) + (lex-tag 'operator lex-js-operator) + (lex-tag 'string (lex-any (lex-delimited "\"") + (lex-delimited "'"))) + ;; TODO: Highlight expressions within template literals. + (lex-tag 'template (lex-delimited "`")) + (lex-tag 'symbol lex-js-identifier)))) -- cgit v1.2.3