scheme.js 5.4 KB
Newer Older
DCloud_JSON's avatar
DCloud_JSON 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
/*
Language: Scheme
Description: Scheme is a programming language in the Lisp family.
             (keywords based on http://community.schemewiki.org/?scheme-keywords)
Author: JP Verkamp <me@jverkamp.com>
Contributors: Ivan Sagalaev <maniac@softwaremaniacs.org>
Origin: clojure.js
Website: http://community.schemewiki.org/?what-is-scheme
Category: lisp
*/

function scheme(hljs) {
  const SCHEME_IDENT_RE = '[^\\(\\)\\[\\]\\{\\}",\'`;#|\\\\\\s]+';
  const SCHEME_SIMPLE_NUMBER_RE = '(-|\\+)?\\d+([./]\\d+)?';
  const SCHEME_COMPLEX_NUMBER_RE = SCHEME_SIMPLE_NUMBER_RE + '[+\\-]' + SCHEME_SIMPLE_NUMBER_RE + 'i';
  const KEYWORDS = {
    $pattern: SCHEME_IDENT_RE,
    built_in:
      'case-lambda call/cc class define-class exit-handler field import '
      + 'inherit init-field interface let*-values let-values let/ec mixin '
      + 'opt-lambda override protect provide public rename require '
      + 'require-for-syntax syntax syntax-case syntax-error unit/sig unless '
      + 'when with-syntax and begin call-with-current-continuation '
      + 'call-with-input-file call-with-output-file case cond define '
      + 'define-syntax delay do dynamic-wind else for-each if lambda let let* '
      + 'let-syntax letrec letrec-syntax map or syntax-rules \' * + , ,@ - ... / '
      + '; < <= = => > >= ` abs acos angle append apply asin assoc assq assv atan '
      + 'boolean? caar cadr call-with-input-file call-with-output-file '
      + 'call-with-values car cdddar cddddr cdr ceiling char->integer '
      + 'char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? '
      + 'char-downcase char-lower-case? char-numeric? char-ready? char-upcase '
      + 'char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? '
      + 'char? close-input-port close-output-port complex? cons cos '
      + 'current-input-port current-output-port denominator display eof-object? '
      + 'eq? equal? eqv? eval even? exact->inexact exact? exp expt floor '
      + 'force gcd imag-part inexact->exact inexact? input-port? integer->char '
      + 'integer? interaction-environment lcm length list list->string '
      + 'list->vector list-ref list-tail list? load log magnitude make-polar '
      + 'make-rectangular make-string make-vector max member memq memv min '
      + 'modulo negative? newline not null-environment null? number->string '
      + 'number? numerator odd? open-input-file open-output-file output-port? '
      + 'pair? peek-char port? positive? procedure? quasiquote quote quotient '
      + 'rational? rationalize read read-char real-part real? remainder reverse '
      + 'round scheme-report-environment set! set-car! set-cdr! sin sqrt string '
      + 'string->list string->number string->symbol string-append string-ci<=? '
      + 'string-ci<? string-ci=? string-ci>=? string-ci>? string-copy '
      + 'string-fill! string-length string-ref string-set! string<=? string<? '
      + 'string=? string>=? string>? string? substring symbol->string symbol? '
      + 'tan transcript-off transcript-on truncate values vector '
      + 'vector->list vector-fill! vector-length vector-ref vector-set! '
      + 'with-input-from-file with-output-to-file write write-char zero?'
  };

  const LITERAL = {
    className: 'literal',
    begin: '(#t|#f|#\\\\' + SCHEME_IDENT_RE + '|#\\\\.)'
  };

  const NUMBER = {
    className: 'number',
    variants: [
      {
        begin: SCHEME_SIMPLE_NUMBER_RE,
        relevance: 0
      },
      {
        begin: SCHEME_COMPLEX_NUMBER_RE,
        relevance: 0
      },
      { begin: '#b[0-1]+(/[0-1]+)?' },
      { begin: '#o[0-7]+(/[0-7]+)?' },
      { begin: '#x[0-9a-f]+(/[0-9a-f]+)?' }
    ]
  };

  const STRING = hljs.QUOTE_STRING_MODE;

  const COMMENT_MODES = [
    hljs.COMMENT(
      ';',
      '$',
      { relevance: 0 }
    ),
    hljs.COMMENT('#\\|', '\\|#')
  ];

  const IDENT = {
    begin: SCHEME_IDENT_RE,
    relevance: 0
  };

  const QUOTED_IDENT = {
    className: 'symbol',
    begin: '\'' + SCHEME_IDENT_RE
  };

  const BODY = {
    endsWithParent: true,
    relevance: 0
  };

  const QUOTED_LIST = {
    variants: [
      { begin: /'/ },
      { begin: '`' }
    ],
    contains: [
      {
        begin: '\\(',
        end: '\\)',
        contains: [
          'self',
          LITERAL,
          STRING,
          NUMBER,
          IDENT,
          QUOTED_IDENT
        ]
      }
    ]
  };

  const NAME = {
    className: 'name',
    relevance: 0,
    begin: SCHEME_IDENT_RE,
    keywords: KEYWORDS
  };

  const LAMBDA = {
    begin: /lambda/,
    endsWithParent: true,
    returnBegin: true,
    contains: [
      NAME,
      {
        endsParent: true,
        variants: [
          {
            begin: /\(/,
            end: /\)/
          },
          {
            begin: /\[/,
            end: /\]/
          }
        ],
        contains: [ IDENT ]
      }
    ]
  };

  const LIST = {
    variants: [
      {
        begin: '\\(',
        end: '\\)'
      },
      {
        begin: '\\[',
        end: '\\]'
      }
    ],
    contains: [
      LAMBDA,
      NAME,
      BODY
    ]
  };

  BODY.contains = [
    LITERAL,
    NUMBER,
    STRING,
    IDENT,
    QUOTED_IDENT,
    QUOTED_LIST,
    LIST
  ].concat(COMMENT_MODES);

  return {
    name: 'Scheme',
    aliases: ['scm'],
    illegal: /\S/,
    contains: [
      hljs.SHEBANG(),
      NUMBER,
      STRING,
      QUOTED_IDENT,
      QUOTED_LIST,
      LIST
    ].concat(COMMENT_MODES)
  };
}

export { scheme as default };