Skip to content

Commit

Permalink
(parser) Build common EMCAscript foundation
Browse files Browse the repository at this point in the history
Builds a common keyword foundation for any grammar that is
building on top of JavaScript:

- LiveScript
- CoffeeScript
- TypeScript

Also uses this common foundation for JS itself.
  • Loading branch information
joshgoebel committed Apr 29, 2020
1 parent 5f1fbf1 commit b984c7b
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 101 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Expand Up @@ -2,7 +2,8 @@ module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
"node": true,
"mocha": true
},
"extends": [
"eslint:recommended",
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -13,6 +13,7 @@ Deprecations:

Language Improvements:

- enh(typescript/javascript/coffeescript/livescript) derive ECMAscript keywords from a common foudation (#2518) [Josh Goebel][]
- enh(typescript) add setInterval, setTimeout, clearInterval, clearTimeout (#2514) [Josh Goebel][]
- enh(javascript) add setInterval, setTimeout, clearInterval, clearTimeout (#2514) [Vania Kucher][]
- fix(javascript) prevent `set` keyword conflicting with setTimeout, etc. (#2514) [Vania Kucher][]
Expand Down
50 changes: 37 additions & 13 deletions src/languages/coffeescript.js
Expand Up @@ -7,21 +7,45 @@ Category: common, scripting
Website: https://coffeescript.org
*/

import * as ECMAScript from "./lib/ecmascript";

export default function(hljs) {
var COFFEE_BUILT_INS = [
'npm',
'print'
];
var COFFEE_LITERALS = [
'yes',
'no',
'on',
'off'
];
var COFFEE_KEYWORDS = [
'then',
'unless',
'until',
'loop',
'by',
'when',
'and',
'or',
'is',
'isnt',
'not'
];
var NOT_VALID_KEYWORDS = [
"var",
"const",
"let",
"function",
"static"
];
var excluding = (list) =>
(kw) => !list.includes(kw);
var KEYWORDS = {
keyword:
// JS keywords
'in if for while finally new do return else break catch instanceof throw try this ' +
'switch continue typeof delete debugger super yield import export from as default await ' +
// Coffee keywords
'then unless until loop of by when and or is isnt not',
literal:
// JS literals
'true false null undefined ' +
// Coffee literals
'yes no on off',
built_in:
'npm require console print module global window document'
keyword: ECMAScript.KEYWORDS.concat(COFFEE_KEYWORDS).filter(excluding(NOT_VALID_KEYWORDS)).join(" "),
literal: ECMAScript.LITERALS.concat(COFFEE_LITERALS).join(" "),
built_in: ECMAScript.BUILT_INS.concat(COFFEE_BUILT_INS).join(" ")
};
var JS_IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
var SUBST = {
Expand Down
23 changes: 5 additions & 18 deletions src/languages/javascript.js
Expand Up @@ -5,6 +5,8 @@ Category: common, scripting
Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
*/

import * as ECMAScript from "./lib/ecmascript";

export default function(hljs) {
var FRAGMENT = {
begin: '<>',
Expand All @@ -16,24 +18,9 @@ export default function(hljs) {
};
var IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
var KEYWORDS = {
keyword:
'in of if for while finally var new function do return void else break catch ' +
'instanceof with throw case default try this switch continue typeof delete ' +
'let yield const export super debugger as async await static ' +
// ECMAScript 6 modules import
'import from as'
,
literal:
'true false null undefined NaN Infinity',
built_in:
'eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent ' +
'encodeURI encodeURIComponent escape unescape Object Function Boolean Error ' +
'EvalError InternalError RangeError ReferenceError StopIteration SyntaxError ' +
'TypeError URIError Number Math Date String RegExp Array Float32Array ' +
'Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array ' +
'Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require ' +
'module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect ' +
'Promise setInterval setTimeout clearInterval clearTimeout'
keyword: ECMAScript.KEYWORDS.join(" "),
literal: ECMAScript.LITERALS.join(" "),
built_in: ECMAScript.BUILT_INS.join(" ")
};
var NUMBER = {
className: 'number',
Expand Down
138 changes: 138 additions & 0 deletions src/languages/lib/ecmascript.js
@@ -0,0 +1,138 @@
const KEYWORDS = [
"as", // for exports
"in",
"of",
"if",
"for",
"while",
"finally",
"var",
"new",
"function",
"do",
"return",
"void",
"else",
"break",
"catch",
"instanceof",
"with",
"throw",
"case",
"default",
"try",
"switch",
"continue",
"typeof",
"delete",
"let",
"yield",
"const",
"class",
// JS handles these with a special rule
// "get",
// "set",
"debugger",
"async",
"await",
"static",
"import",
"from",
"export",
"extends"
];
const LITERALS = [
"true",
"false",
"null",
"undefined",
"NaN",
"Infinity"
];

const TYPES = [
"Intl",
"DataView",
"Number",
"Math",
"Date",
"String",
"RegExp",
"Object",
"Function",
"Boolean",
"Error",
"Symbol",
"Set",
"Map",
"WeakSet",
"WeakMap",
"Proxy",
"Reflect",
"JSON",
"Promise",
"Float64Array",
"Int16Array",
"Int32Array",
"Int8Array",
"Uint16Array",
"Uint32Array",
"Float32Array",
"Array",
"Uint8Array",
"Uint8ClampedArray",
"ArrayBuffer"
];

const ERROR_TYPES = [
"EvalError",
"InternalError",
"RangeError",
"ReferenceError",
"SyntaxError",
"TypeError",
"URIError"
];

const BUILT_IN_GLOBALS = [
"setInterval",
"setTimeout",
"clearInterval",
"clearTimeout",

"require",
"exports",

"eval",
"isFinite",
"isNaN",
"parseFloat",
"parseInt",
"decodeURI",
"decodeURIComponent",
"encodeURI",
"encodeURIComponent",
"escape",
"unescape"
];

const BUILT_IN_VARIABLES = [
"arguments",
"this",
"super",
"console",
"window",
"document",
"localStorage",
"module",
"global" // Node.js
];

const BUILT_INS = [].concat(
BUILT_IN_GLOBALS,
BUILT_IN_VARIABLES,
TYPES,
ERROR_TYPES
);

export { LITERALS, BUILT_INS, KEYWORDS };
64 changes: 49 additions & 15 deletions src/languages/livescript.js
Expand Up @@ -8,23 +8,57 @@ Website: https://livescript.net
Category: scripting
*/

import * as ECMAScript from "./lib/ecmascript";

export default function(hljs) {
var LIVESCRIPT_BUILT_INS = [
'npm',
'print'
];
var LIVESCRIPT_LITERALS = [
'yes',
'no',
'on',
'off',
'it',
'that',
'void'
];
var LIVESCRIPT_KEYWORDS = [
'then',
'unless',
'until',
'loop',
'of',
'by',
'when',
'and',
'or',
'is',
'isnt',
'not',
'it',
'that',
'otherwise',
'from',
'to',
'til',
'fallthrough',
'case',
'enum',
'native',
'list',
'map',
'__hasProp',
'__extends',
'__slice',
'__bind',
'__indexOf'
];
var KEYWORDS = {
keyword:
// JS keywords
'in if for while finally new do return else break catch instanceof throw try this ' +
'switch continue typeof delete debugger case default function var with ' +
// LiveScript keywords
'then unless until loop of by when and or is isnt not it that otherwise from to til fallthrough super ' +
'case default function var void const let enum export import native list map ' +
'__hasProp __extends __slice __bind __indexOf',
literal:
// JS literals
'true false null undefined ' +
// LiveScript literals
'yes no on off it that void',
built_in:
'npm require console print module global window document'
keyword: ECMAScript.KEYWORDS.concat(LIVESCRIPT_KEYWORDS).join(" "),
literal: ECMAScript.LITERALS.concat(LIVESCRIPT_LITERALS).join(" "),
built_in: ECMAScript.BUILT_INS.concat(LIVESCRIPT_BUILT_INS).join(" ")
};
var JS_IDENT_RE = '[A-Za-z$_](?:\-[0-9A-Za-z$_]|[0-9A-Za-z$_])*';
var TITLE = hljs.inherit(hljs.TITLE_MODE, {begin: JS_IDENT_RE});
Expand Down
44 changes: 27 additions & 17 deletions src/languages/typescript.js
Expand Up @@ -7,26 +7,36 @@ Website: https://www.typescriptlang.org
Category: common, scripting
*/

import * as ECMAScript from "./lib/ecmascript";

export default function(hljs) {
var JS_IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
var TYPES = [
"any",
"void",
"number",
"boolean",
"string",
"object",
"never",
"enum"
];
var TS_SPECIFIC_KEYWORDS = [
"type",
"namespace",
"typedef",
"interface",
"public",
"private",
"protected",
"implements",
"declare",
"abstract"
];
var KEYWORDS = {
keyword:
'in if for while finally var new function do return void else break catch ' +
'instanceof with throw case default try this switch continue typeof delete ' +
'let yield const class public private protected get set super ' +
'static implements enum export import declare type namespace abstract ' +
'as from extends async await',
literal:
'true false null undefined NaN Infinity',
built_in:
'eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent ' +
'encodeURI encodeURIComponent escape unescape Object Function Boolean Error ' +
'EvalError InternalError RangeError ReferenceError StopIteration SyntaxError ' +
'TypeError URIError Number Math Date String RegExp Array Float32Array ' +
'Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array ' +
'Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require ' +
'module console window document any number boolean string void Promise ' +
'setInterval setTimeout clearInterval clearTimeout'
keyword: ECMAScript.KEYWORDS.concat(TS_SPECIFIC_KEYWORDS).join(" "),
literal: ECMAScript.LITERALS.join(" "),
built_in: ECMAScript.BUILT_INS.concat(TYPES).join(" ")
};
var DECORATOR = {
className: 'meta',
Expand Down

0 comments on commit b984c7b

Please sign in to comment.