@sormy/lemon-js 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +12 -0
- package/README.md +194 -0
- package/bin/lemon-js.js +50 -0
- package/dist/lemon-js-darwin-universal +0 -0
- package/dist/lemon-js-linux-arm64 +0 -0
- package/dist/lemon-js-linux-x64 +0 -0
- package/dist/lemon-js-win32-arm64.exe +0 -0
- package/dist/lemon-js-win32-x64.exe +0 -0
- package/examples/calculator-js.y +74 -0
- package/lemon-js.c +5537 -0
- package/lemon.html +987 -0
- package/lempar.js +779 -0
- package/lexer/lexer.js +82 -0
- package/package.json +47 -0
package/lexer/lexer.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive Lexer.
|
|
3
|
+
*
|
|
4
|
+
* This is single-state primitive lexer which will try to test each added rule
|
|
5
|
+
* one by one. First matched rule will be used to get token text.
|
|
6
|
+
*
|
|
7
|
+
* It could be used only for primitive grammars but also could be a good starting
|
|
8
|
+
* point for writing your own lexer. For longest match, start conditions and
|
|
9
|
+
* actions, see flex-js: https://github.com/sormy/flex-js
|
|
10
|
+
*/
|
|
11
|
+
function Lexer() {
|
|
12
|
+
this.index = 0;
|
|
13
|
+
this.rules = [];
|
|
14
|
+
this.input = '';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
Lexer.prototype.addRule = function (expression, handler) {
|
|
18
|
+
if (typeof expression === 'string') {
|
|
19
|
+
expression = new RegExp(this.escapeRE(expression), 'y');
|
|
20
|
+
}
|
|
21
|
+
if (expression instanceof RegExp && !expression.sticky) {
|
|
22
|
+
expression = new RegExp(expression.source, expression.flags + 'y');
|
|
23
|
+
}
|
|
24
|
+
this.rules.push([ expression, handler ]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Lexer.prototype.setInput = function (input) {
|
|
28
|
+
this.input = input;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Lexer.prototype.escapeRE = function (s) {
|
|
32
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Lexer.prototype.execRE = function (re) {
|
|
36
|
+
re.lastIndex = this.index;
|
|
37
|
+
var result = re.exec(this.input);
|
|
38
|
+
return result ? result[0] : undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Lexer.prototype.raiseSyntaxError = function () {
|
|
42
|
+
throw new Error('Syntax error');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Lexer.prototype.lex = function () {
|
|
46
|
+
if (this.index >= this.input.length) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var token;
|
|
51
|
+
var matched;
|
|
52
|
+
|
|
53
|
+
do {
|
|
54
|
+
matched = false;
|
|
55
|
+
|
|
56
|
+
for (var index = 0; index < this.rules.length; index++) {
|
|
57
|
+
var rule = this.rules[index];
|
|
58
|
+
|
|
59
|
+
var expression = rule[0];
|
|
60
|
+
var handler = rule[1];
|
|
61
|
+
|
|
62
|
+
var value = this.execRE(expression);
|
|
63
|
+
|
|
64
|
+
// a rule matching nothing would leave the position where it was
|
|
65
|
+
if (value) {
|
|
66
|
+
token = handler(value);
|
|
67
|
+
matched = true;
|
|
68
|
+
this.index += value.length;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// undefined token with match is a sign that we need to search next token
|
|
73
|
+
} while (matched && token === undefined && this.index < this.input.length);
|
|
74
|
+
|
|
75
|
+
if (!matched) {
|
|
76
|
+
this.raiseSyntaxError();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return token;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = Lexer;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sormy/lemon-js",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "LALR(1) parser generator for JavaScript, based on the lemon generator from SQLite",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"lemon",
|
|
7
|
+
"lalr",
|
|
8
|
+
"parser",
|
|
9
|
+
"parser-generator",
|
|
10
|
+
"grammar",
|
|
11
|
+
"compiler"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/sormy/lemon-js#readme",
|
|
14
|
+
"bugs": "https://github.com/sormy/lemon-js/issues",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/sormy/lemon-js.git"
|
|
18
|
+
},
|
|
19
|
+
"license": "blessing",
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"author": "Artem Butusov <art.sormy@gmail.com>",
|
|
24
|
+
"bin": {
|
|
25
|
+
"lemon-js": "bin/lemon-js.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/",
|
|
29
|
+
"dist/",
|
|
30
|
+
"lexer/lexer.js",
|
|
31
|
+
"examples/calculator-js.y",
|
|
32
|
+
"lempar.js",
|
|
33
|
+
"lemon-js.c",
|
|
34
|
+
"lemon.html",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "./build-dist.sh",
|
|
39
|
+
"pretest": "gcc -o lemon-js -O2 lemon-js.c",
|
|
40
|
+
"test": "node --test test/*.test.js",
|
|
41
|
+
"test:dist": "LEMON_JS=bin/lemon-js.js node --test test/*.test.js",
|
|
42
|
+
"prepublishOnly": "npm run build && npm run test:dist"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=12"
|
|
46
|
+
}
|
|
47
|
+
}
|