grammar-well 1.1.2 → 1.1.3
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/build/compiler/compiler.d.ts +49 -49
- package/build/compiler/compiler.js +227 -227
- package/build/compiler/generator.d.ts +23 -23
- package/build/compiler/generator.js +213 -212
- package/build/compiler/generator.js.map +1 -1
- package/build/compiler/import-resolver.d.ts +15 -15
- package/build/compiler/import-resolver.js +36 -36
- package/build/compiler/outputs/javascript.d.ts +3 -3
- package/build/compiler/outputs/javascript.js +14 -14
- package/build/compiler/outputs/json.d.ts +2 -2
- package/build/compiler/outputs/json.js +7 -7
- package/build/compiler/outputs/typescript.d.ts +2 -2
- package/build/compiler/outputs/typescript.js +9 -8
- package/build/compiler/outputs/typescript.js.map +1 -1
- package/build/grammars/gwell.d.ts +1023 -997
- package/build/grammars/gwell.js +540 -536
- package/build/grammars/gwell.js.map +1 -1
- package/build/grammars/json.d.ts +151 -151
- package/build/grammars/json.js +111 -111
- package/build/grammars/number.d.ts +239 -239
- package/build/grammars/number.js +114 -114
- package/build/grammars/number.json +1 -1
- package/build/grammars/string.d.ts +116 -116
- package/build/grammars/string.js +49 -49
- package/build/grammars/string.json +1 -1
- package/build/grammars/whitespace.d.ts +51 -51
- package/build/grammars/whitespace.js +29 -29
- package/build/grammars/whitespace.json +1 -1
- package/build/index.d.ts +4 -4
- package/build/index.js +20 -20
- package/build/lexers/character-lexer.d.ts +27 -27
- package/build/lexers/character-lexer.js +70 -70
- package/build/lexers/stateful-lexer.d.ts +48 -48
- package/build/lexers/stateful-lexer.js +308 -308
- package/build/lexers/token-buffer.d.ts +32 -32
- package/build/lexers/token-buffer.js +91 -91
- package/build/parser/algorithms/cyk.d.ts +16 -16
- package/build/parser/algorithms/cyk.js +57 -57
- package/build/parser/algorithms/earley.d.ts +48 -48
- package/build/parser/algorithms/earley.js +157 -157
- package/build/parser/algorithms/lr.d.ts +10 -10
- package/build/parser/algorithms/lr.js +33 -33
- package/build/parser/parser.d.ts +26 -26
- package/build/parser/parser.js +73 -73
- package/build/typings.d.ts +199 -198
- package/build/typings.js +2 -2
- package/build/utility/general.d.ts +55 -55
- package/build/utility/general.js +165 -165
- package/build/utility/lint.d.ts +2 -2
- package/build/utility/lint.js +27 -27
- package/build/utility/lr.d.ts +52 -52
- package/build/utility/lr.js +129 -129
- package/build/utility/text-format.d.ts +11 -11
- package/build/utility/text-format.js +83 -83
- package/package.json +1 -1
- package/src/compiler/generator.ts +1 -0
- package/src/compiler/outputs/typescript.ts +2 -1
- package/src/grammars/gwell.gwell +15 -13
- package/src/grammars/gwell.js +17 -13
- package/src/grammars/gwell.json +1 -1
- package/src/typings.ts +1 -0
package/build/utility/lr.js
CHANGED
|
@@ -1,130 +1,130 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LRStack = exports.CanonicalCollection = void 0;
|
|
4
|
-
const parser_1 = require("../parser/parser");
|
|
5
|
-
const general_1 = require("./general");
|
|
6
|
-
class CanonicalCollection {
|
|
7
|
-
grammar;
|
|
8
|
-
rules = new general_1.Collection();
|
|
9
|
-
states = Object.create(null);
|
|
10
|
-
symbols = new general_1.SymbolCollection();
|
|
11
|
-
constructor(grammar) {
|
|
12
|
-
this.grammar = grammar;
|
|
13
|
-
const augmented = { name: Symbol(), symbols: [grammar.start] };
|
|
14
|
-
grammar.rules[augmented.name] = [augmented];
|
|
15
|
-
this.addState([{ rule: augmented, dot: 0 }]);
|
|
16
|
-
}
|
|
17
|
-
addState(seed) {
|
|
18
|
-
const id = this.encodeStateItems(seed);
|
|
19
|
-
if (id in this.states)
|
|
20
|
-
return this.states[id];
|
|
21
|
-
const state = new State(this, seed);
|
|
22
|
-
this.states[id] = state;
|
|
23
|
-
for (const q in state.queue) {
|
|
24
|
-
this.addState(state.queue[q]);
|
|
25
|
-
}
|
|
26
|
-
state.queue = {};
|
|
27
|
-
}
|
|
28
|
-
encodeRule(rule, dot) {
|
|
29
|
-
return this.rules.encode(rule) + '.' + dot;
|
|
30
|
-
}
|
|
31
|
-
encodeStateItems(seed) {
|
|
32
|
-
return Array.from(new Set(seed)).map(v => this.encodeRule(v.rule, v.dot)).sort().join();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
exports.CanonicalCollection = CanonicalCollection;
|
|
36
|
-
class State {
|
|
37
|
-
collection;
|
|
38
|
-
isFinal = false;
|
|
39
|
-
outputs = {
|
|
40
|
-
goto: {},
|
|
41
|
-
action: {}
|
|
42
|
-
};
|
|
43
|
-
queue = {};
|
|
44
|
-
actions = new Map();
|
|
45
|
-
goto = new Map();
|
|
46
|
-
reduce;
|
|
47
|
-
constructor(collection, items) {
|
|
48
|
-
this.collection = collection;
|
|
49
|
-
const visited = new Set();
|
|
50
|
-
for (const item of items) {
|
|
51
|
-
this.closure(item.rule, item.dot, visited);
|
|
52
|
-
}
|
|
53
|
-
if (this.isFinal) {
|
|
54
|
-
if (items.length == 1 && visited.size < 1) {
|
|
55
|
-
this.reduce = items[0].rule;
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
throw 'Conflict Detected';
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
for (const k in this.outputs.goto) {
|
|
62
|
-
const seed = this.outputs.goto[k];
|
|
63
|
-
const stateId = this.collection.encodeStateItems(seed);
|
|
64
|
-
this.queue[stateId] = seed;
|
|
65
|
-
this.goto.set(this.collection.symbols.decode(k), stateId);
|
|
66
|
-
}
|
|
67
|
-
for (const k in this.outputs.action) {
|
|
68
|
-
const seed = this.outputs.action[k];
|
|
69
|
-
const stateId = this.collection.encodeStateItems(seed);
|
|
70
|
-
this.queue[stateId] = seed;
|
|
71
|
-
this.actions.set(this.collection.symbols.decode(k), stateId);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
closure(rule, dot, visited) {
|
|
75
|
-
const isFinal = rule.symbols.length == dot;
|
|
76
|
-
this.isFinal = isFinal || this.isFinal;
|
|
77
|
-
const { [dot]: symbol } = rule.symbols;
|
|
78
|
-
if (isFinal || visited.has(symbol))
|
|
79
|
-
return;
|
|
80
|
-
visited.add(symbol);
|
|
81
|
-
const stateItem = { rule, dot: dot + 1 };
|
|
82
|
-
if (parser_1.ParserUtility.SymbolIsTerminal(symbol)) {
|
|
83
|
-
const id = this.collection.symbols.encode(symbol);
|
|
84
|
-
this.outputs.action[id] = this.outputs.action[id] || [];
|
|
85
|
-
this.outputs.action[id].push(stateItem);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
const id = this.collection.symbols.encode(symbol);
|
|
89
|
-
this.outputs.goto[id] = this.outputs.goto[id] || [];
|
|
90
|
-
this.outputs.goto[id].push(stateItem);
|
|
91
|
-
for (const rule of this.collection.grammar.rules[symbol]) {
|
|
92
|
-
this.closure(rule, 0, visited);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
class LRStack {
|
|
98
|
-
stack = [];
|
|
99
|
-
get current() {
|
|
100
|
-
return this.stack[this.stack.length - 1];
|
|
101
|
-
}
|
|
102
|
-
get previous() {
|
|
103
|
-
return this.stack[this.stack.length - 2];
|
|
104
|
-
}
|
|
105
|
-
shift(state) {
|
|
106
|
-
this.current.state = state;
|
|
107
|
-
}
|
|
108
|
-
reduce(rule) {
|
|
109
|
-
const n = new LRStackItem();
|
|
110
|
-
const l = rule.symbols.length;
|
|
111
|
-
n.children = this.stack.splice(l * -1, l);
|
|
112
|
-
n.children.forEach(v => delete v.state);
|
|
113
|
-
n.rule = rule;
|
|
114
|
-
n.symbol = rule.name;
|
|
115
|
-
this.stack.push(n);
|
|
116
|
-
}
|
|
117
|
-
add(symbol) {
|
|
118
|
-
this.stack.push(new LRStackItem());
|
|
119
|
-
this.current.symbol = symbol;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
exports.LRStack = LRStack;
|
|
123
|
-
class LRStackItem {
|
|
124
|
-
children = [];
|
|
125
|
-
state;
|
|
126
|
-
symbol;
|
|
127
|
-
rule;
|
|
128
|
-
value;
|
|
129
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LRStack = exports.CanonicalCollection = void 0;
|
|
4
|
+
const parser_1 = require("../parser/parser");
|
|
5
|
+
const general_1 = require("./general");
|
|
6
|
+
class CanonicalCollection {
|
|
7
|
+
grammar;
|
|
8
|
+
rules = new general_1.Collection();
|
|
9
|
+
states = Object.create(null);
|
|
10
|
+
symbols = new general_1.SymbolCollection();
|
|
11
|
+
constructor(grammar) {
|
|
12
|
+
this.grammar = grammar;
|
|
13
|
+
const augmented = { name: Symbol(), symbols: [grammar.start] };
|
|
14
|
+
grammar.rules[augmented.name] = [augmented];
|
|
15
|
+
this.addState([{ rule: augmented, dot: 0 }]);
|
|
16
|
+
}
|
|
17
|
+
addState(seed) {
|
|
18
|
+
const id = this.encodeStateItems(seed);
|
|
19
|
+
if (id in this.states)
|
|
20
|
+
return this.states[id];
|
|
21
|
+
const state = new State(this, seed);
|
|
22
|
+
this.states[id] = state;
|
|
23
|
+
for (const q in state.queue) {
|
|
24
|
+
this.addState(state.queue[q]);
|
|
25
|
+
}
|
|
26
|
+
state.queue = {};
|
|
27
|
+
}
|
|
28
|
+
encodeRule(rule, dot) {
|
|
29
|
+
return this.rules.encode(rule) + '.' + dot;
|
|
30
|
+
}
|
|
31
|
+
encodeStateItems(seed) {
|
|
32
|
+
return Array.from(new Set(seed)).map(v => this.encodeRule(v.rule, v.dot)).sort().join();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.CanonicalCollection = CanonicalCollection;
|
|
36
|
+
class State {
|
|
37
|
+
collection;
|
|
38
|
+
isFinal = false;
|
|
39
|
+
outputs = {
|
|
40
|
+
goto: {},
|
|
41
|
+
action: {}
|
|
42
|
+
};
|
|
43
|
+
queue = {};
|
|
44
|
+
actions = new Map();
|
|
45
|
+
goto = new Map();
|
|
46
|
+
reduce;
|
|
47
|
+
constructor(collection, items) {
|
|
48
|
+
this.collection = collection;
|
|
49
|
+
const visited = new Set();
|
|
50
|
+
for (const item of items) {
|
|
51
|
+
this.closure(item.rule, item.dot, visited);
|
|
52
|
+
}
|
|
53
|
+
if (this.isFinal) {
|
|
54
|
+
if (items.length == 1 && visited.size < 1) {
|
|
55
|
+
this.reduce = items[0].rule;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw 'Conflict Detected';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const k in this.outputs.goto) {
|
|
62
|
+
const seed = this.outputs.goto[k];
|
|
63
|
+
const stateId = this.collection.encodeStateItems(seed);
|
|
64
|
+
this.queue[stateId] = seed;
|
|
65
|
+
this.goto.set(this.collection.symbols.decode(k), stateId);
|
|
66
|
+
}
|
|
67
|
+
for (const k in this.outputs.action) {
|
|
68
|
+
const seed = this.outputs.action[k];
|
|
69
|
+
const stateId = this.collection.encodeStateItems(seed);
|
|
70
|
+
this.queue[stateId] = seed;
|
|
71
|
+
this.actions.set(this.collection.symbols.decode(k), stateId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
closure(rule, dot, visited) {
|
|
75
|
+
const isFinal = rule.symbols.length == dot;
|
|
76
|
+
this.isFinal = isFinal || this.isFinal;
|
|
77
|
+
const { [dot]: symbol } = rule.symbols;
|
|
78
|
+
if (isFinal || visited.has(symbol))
|
|
79
|
+
return;
|
|
80
|
+
visited.add(symbol);
|
|
81
|
+
const stateItem = { rule, dot: dot + 1 };
|
|
82
|
+
if (parser_1.ParserUtility.SymbolIsTerminal(symbol)) {
|
|
83
|
+
const id = this.collection.symbols.encode(symbol);
|
|
84
|
+
this.outputs.action[id] = this.outputs.action[id] || [];
|
|
85
|
+
this.outputs.action[id].push(stateItem);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const id = this.collection.symbols.encode(symbol);
|
|
89
|
+
this.outputs.goto[id] = this.outputs.goto[id] || [];
|
|
90
|
+
this.outputs.goto[id].push(stateItem);
|
|
91
|
+
for (const rule of this.collection.grammar.rules[symbol]) {
|
|
92
|
+
this.closure(rule, 0, visited);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
class LRStack {
|
|
98
|
+
stack = [];
|
|
99
|
+
get current() {
|
|
100
|
+
return this.stack[this.stack.length - 1];
|
|
101
|
+
}
|
|
102
|
+
get previous() {
|
|
103
|
+
return this.stack[this.stack.length - 2];
|
|
104
|
+
}
|
|
105
|
+
shift(state) {
|
|
106
|
+
this.current.state = state;
|
|
107
|
+
}
|
|
108
|
+
reduce(rule) {
|
|
109
|
+
const n = new LRStackItem();
|
|
110
|
+
const l = rule.symbols.length;
|
|
111
|
+
n.children = this.stack.splice(l * -1, l);
|
|
112
|
+
n.children.forEach(v => delete v.state);
|
|
113
|
+
n.rule = rule;
|
|
114
|
+
n.symbol = rule.name;
|
|
115
|
+
this.stack.push(n);
|
|
116
|
+
}
|
|
117
|
+
add(symbol) {
|
|
118
|
+
this.stack.push(new LRStackItem());
|
|
119
|
+
this.current.symbol = symbol;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.LRStack = LRStack;
|
|
123
|
+
class LRStackItem {
|
|
124
|
+
children = [];
|
|
125
|
+
state;
|
|
126
|
+
symbol;
|
|
127
|
+
rule;
|
|
128
|
+
value;
|
|
129
|
+
}
|
|
130
130
|
//# sourceMappingURL=lr.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { TokenBuffer } from "../lexers/token-buffer";
|
|
2
|
-
import { GrammarRule, GrammarRuleSymbol, LexerToken } from "../typings";
|
|
3
|
-
export declare class TextFormatter {
|
|
4
|
-
static UnexpectedToken(queue: TokenBuffer, expected: (GrammarRule & {
|
|
5
|
-
index?: number;
|
|
6
|
-
})[]): string;
|
|
7
|
-
static LexerTokenShort(token: LexerToken): string;
|
|
8
|
-
static LexerTokenError(lexer: TokenBuffer): string;
|
|
9
|
-
static GrammarRuleSymbol(symbol: GrammarRuleSymbol, short?: boolean, error?: boolean): string;
|
|
10
|
-
static GrammarRule(rule: GrammarRule, withCursorAt?: number): string;
|
|
11
|
-
}
|
|
1
|
+
import { TokenBuffer } from "../lexers/token-buffer";
|
|
2
|
+
import { GrammarRule, GrammarRuleSymbol, LexerToken } from "../typings";
|
|
3
|
+
export declare class TextFormatter {
|
|
4
|
+
static UnexpectedToken(queue: TokenBuffer, expected: (GrammarRule & {
|
|
5
|
+
index?: number;
|
|
6
|
+
})[]): string;
|
|
7
|
+
static LexerTokenShort(token: LexerToken): string;
|
|
8
|
+
static LexerTokenError(lexer: TokenBuffer): string;
|
|
9
|
+
static GrammarRuleSymbol(symbol: GrammarRuleSymbol, short?: boolean, error?: boolean): string;
|
|
10
|
+
static GrammarRule(rule: GrammarRule, withCursorAt?: number): string;
|
|
11
|
+
}
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TextFormatter = void 0;
|
|
4
|
-
class TextFormatter {
|
|
5
|
-
static UnexpectedToken(queue, expected) {
|
|
6
|
-
const token = queue.active;
|
|
7
|
-
const tokenDisplay = TextFormatter.LexerTokenShort(token);
|
|
8
|
-
const lines = [];
|
|
9
|
-
lines.push('Unexpected token: ' + tokenDisplay + ' at line: ' + token.line + ' column: ' + token.column);
|
|
10
|
-
if (expected.length === 0) {
|
|
11
|
-
lines.push('End of input was expected.');
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
lines.push('Instead, I was expecting to see one of the following:\n');
|
|
15
|
-
for (const ex of expected) {
|
|
16
|
-
const nextSymbol = ex.symbols[ex.index];
|
|
17
|
-
const symbolDisplay = TextFormatter.GrammarRuleSymbol(nextSymbol, false, true);
|
|
18
|
-
lines.push('A ' + symbolDisplay + ' based on:');
|
|
19
|
-
lines.push(TextFormatter.GrammarRule(ex, ex.index));
|
|
20
|
-
}
|
|
21
|
-
lines.push("");
|
|
22
|
-
return lines.join("\n");
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
static LexerTokenShort(token) {
|
|
26
|
-
if (token.type)
|
|
27
|
-
return `[${token.type}] ${JSON.stringify(token.value)}`;
|
|
28
|
-
return `${JSON.stringify(token.value)}`;
|
|
29
|
-
}
|
|
30
|
-
static LexerTokenError(lexer) {
|
|
31
|
-
let i = 0;
|
|
32
|
-
let token;
|
|
33
|
-
let string = lexer.peek(i).value;
|
|
34
|
-
let lines = 0;
|
|
35
|
-
const { line, column, offset } = lexer;
|
|
36
|
-
while (token = lexer.peek(--i)) {
|
|
37
|
-
if (token.value == '\n') {
|
|
38
|
-
lines++;
|
|
39
|
-
string = `${(line + 2 - lines)} ${string}`;
|
|
40
|
-
}
|
|
41
|
-
string = token.value + string;
|
|
42
|
-
if (lines >= 2)
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
string = `${line + 2 - (lines + 1)} ${string}`;
|
|
46
|
-
const n = string.lastIndexOf('\n');
|
|
47
|
-
const pad = (string.length - n);
|
|
48
|
-
string += '\n' + '^'.padStart(pad - 1);
|
|
49
|
-
if (typeof column != 'undefined' && typeof line != 'undefined')
|
|
50
|
-
return `Syntax error at line ${line + 1} col ${column + 1}:\n\n${string}\n`;
|
|
51
|
-
return `Syntax error at index ${offset}:\n\n${string}\n`;
|
|
52
|
-
}
|
|
53
|
-
static GrammarRuleSymbol(symbol, short, error) {
|
|
54
|
-
if (typeof symbol === 'string') {
|
|
55
|
-
return symbol;
|
|
56
|
-
}
|
|
57
|
-
else if (typeof symbol === 'function') {
|
|
58
|
-
return short ? `<${symbol.toString()}>` : `token matching ${symbol.toString()}`;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
if ("literal" in symbol) {
|
|
62
|
-
return JSON.stringify(symbol.literal);
|
|
63
|
-
}
|
|
64
|
-
else if (symbol instanceof RegExp) {
|
|
65
|
-
return short ? symbol.toString() : `character matching ${symbol.toString()}`;
|
|
66
|
-
}
|
|
67
|
-
else if ("token" in symbol) {
|
|
68
|
-
return short ? `%${symbol.token}` : `${symbol.token} token`;
|
|
69
|
-
}
|
|
70
|
-
else if (error) {
|
|
71
|
-
return 'Unknown symbol type: ' + JSON.stringify(symbol);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
static GrammarRule(rule, withCursorAt) {
|
|
76
|
-
let symbolSequence = rule.symbols.slice(0, withCursorAt).map(v => TextFormatter.GrammarRuleSymbol(v, true, true)).join(' ');
|
|
77
|
-
if (typeof withCursorAt !== "undefined") {
|
|
78
|
-
symbolSequence += " ● " + rule.symbols.slice(withCursorAt).map(v => TextFormatter.GrammarRuleSymbol(v, true, true)).join(' ');
|
|
79
|
-
}
|
|
80
|
-
return rule.name + " → " + symbolSequence;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
exports.TextFormatter = TextFormatter;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TextFormatter = void 0;
|
|
4
|
+
class TextFormatter {
|
|
5
|
+
static UnexpectedToken(queue, expected) {
|
|
6
|
+
const token = queue.active;
|
|
7
|
+
const tokenDisplay = TextFormatter.LexerTokenShort(token);
|
|
8
|
+
const lines = [];
|
|
9
|
+
lines.push('Unexpected token: ' + tokenDisplay + ' at line: ' + token.line + ' column: ' + token.column);
|
|
10
|
+
if (expected.length === 0) {
|
|
11
|
+
lines.push('End of input was expected.');
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
lines.push('Instead, I was expecting to see one of the following:\n');
|
|
15
|
+
for (const ex of expected) {
|
|
16
|
+
const nextSymbol = ex.symbols[ex.index];
|
|
17
|
+
const symbolDisplay = TextFormatter.GrammarRuleSymbol(nextSymbol, false, true);
|
|
18
|
+
lines.push('A ' + symbolDisplay + ' based on:');
|
|
19
|
+
lines.push(TextFormatter.GrammarRule(ex, ex.index));
|
|
20
|
+
}
|
|
21
|
+
lines.push("");
|
|
22
|
+
return lines.join("\n");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
static LexerTokenShort(token) {
|
|
26
|
+
if (token.type)
|
|
27
|
+
return `[${token.type}] ${JSON.stringify(token.value)}`;
|
|
28
|
+
return `${JSON.stringify(token.value)}`;
|
|
29
|
+
}
|
|
30
|
+
static LexerTokenError(lexer) {
|
|
31
|
+
let i = 0;
|
|
32
|
+
let token;
|
|
33
|
+
let string = lexer.peek(i).value;
|
|
34
|
+
let lines = 0;
|
|
35
|
+
const { line, column, offset } = lexer;
|
|
36
|
+
while (token = lexer.peek(--i)) {
|
|
37
|
+
if (token.value == '\n') {
|
|
38
|
+
lines++;
|
|
39
|
+
string = `${(line + 2 - lines)} ${string}`;
|
|
40
|
+
}
|
|
41
|
+
string = token.value + string;
|
|
42
|
+
if (lines >= 2)
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
string = `${line + 2 - (lines + 1)} ${string}`;
|
|
46
|
+
const n = string.lastIndexOf('\n');
|
|
47
|
+
const pad = (string.length - n);
|
|
48
|
+
string += '\n' + '^'.padStart(pad - 1);
|
|
49
|
+
if (typeof column != 'undefined' && typeof line != 'undefined')
|
|
50
|
+
return `Syntax error at line ${line + 1} col ${column + 1}:\n\n${string}\n`;
|
|
51
|
+
return `Syntax error at index ${offset}:\n\n${string}\n`;
|
|
52
|
+
}
|
|
53
|
+
static GrammarRuleSymbol(symbol, short, error) {
|
|
54
|
+
if (typeof symbol === 'string') {
|
|
55
|
+
return symbol;
|
|
56
|
+
}
|
|
57
|
+
else if (typeof symbol === 'function') {
|
|
58
|
+
return short ? `<${symbol.toString()}>` : `token matching ${symbol.toString()}`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if ("literal" in symbol) {
|
|
62
|
+
return JSON.stringify(symbol.literal);
|
|
63
|
+
}
|
|
64
|
+
else if (symbol instanceof RegExp) {
|
|
65
|
+
return short ? symbol.toString() : `character matching ${symbol.toString()}`;
|
|
66
|
+
}
|
|
67
|
+
else if ("token" in symbol) {
|
|
68
|
+
return short ? `%${symbol.token}` : `${symbol.token} token`;
|
|
69
|
+
}
|
|
70
|
+
else if (error) {
|
|
71
|
+
return 'Unknown symbol type: ' + JSON.stringify(symbol);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
static GrammarRule(rule, withCursorAt) {
|
|
76
|
+
let symbolSequence = rule.symbols.slice(0, withCursorAt).map(v => TextFormatter.GrammarRuleSymbol(v, true, true)).join(' ');
|
|
77
|
+
if (typeof withCursorAt !== "undefined") {
|
|
78
|
+
symbolSequence += " ● " + rule.symbols.slice(withCursorAt).map(v => TextFormatter.GrammarRuleSymbol(v, true, true)).join(' ');
|
|
79
|
+
}
|
|
80
|
+
return rule.name + " → " + symbolSequence;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.TextFormatter = TextFormatter;
|
|
84
84
|
//# sourceMappingURL=text-format.js.map
|
package/package.json
CHANGED
|
@@ -187,6 +187,7 @@ export class Generator {
|
|
|
187
187
|
type: JSON.stringify(rule.type),
|
|
188
188
|
tag: JSON.stringify(rule.tag),
|
|
189
189
|
pop: JSON.stringify(rule.pop),
|
|
190
|
+
highlight: JSON.stringify(rule.highlight),
|
|
190
191
|
set: JSON.stringify(rule.set),
|
|
191
192
|
inset: JSON.stringify(rule.inset),
|
|
192
193
|
goto: JSON.stringify(rule.goto),
|
package/src/grammars/gwell.gwell
CHANGED
|
@@ -3,9 +3,9 @@ lexer: {{
|
|
|
3
3
|
|
|
4
4
|
start ->
|
|
5
5
|
- import: string, js, ws, comment, l_scolon, l_star
|
|
6
|
-
- when: /lexer(?![a-zA-Z\d_])/ tag: "T_WORD" goto: lexer
|
|
7
|
-
- when: /grammar(?![a-zA-Z\d_])/ tag: "T_WORD" goto: grammar
|
|
8
|
-
- when: /config(?![a-zA-Z\d_])/ tag: "T_WORD" goto: config
|
|
6
|
+
- when: /lexer(?![a-zA-Z\d_])/ tag: "T_WORD" goto: lexer highlight: "type"
|
|
7
|
+
- when: /grammar(?![a-zA-Z\d_])/ tag: "T_WORD" goto: grammar highlight: "type"
|
|
8
|
+
- when: /config(?![a-zA-Z\d_])/ tag: "T_WORD" goto: config highlight: "type"
|
|
9
9
|
- import: kv
|
|
10
10
|
config ->
|
|
11
11
|
- import: ws, l_colon
|
|
@@ -57,21 +57,21 @@ lexer: {{
|
|
|
57
57
|
- when: /\/\/[^\n]*/ tag: "T_JSBODY"
|
|
58
58
|
- when: /\/\*.*\*\// tag: "T_JSBODY"
|
|
59
59
|
string ->
|
|
60
|
-
- when: /"(?:[^"\\\r\n]|\\.)*"/ tag: "T_STRING"
|
|
60
|
+
- when: /"(?:[^"\\\r\n]|\\.)*"/ tag: "T_STRING" highlight: "string"
|
|
61
61
|
string2 ->
|
|
62
|
-
- when: /'(?:[^'\\\r\n]|\\.)*'/ tag: "T_STRING"
|
|
62
|
+
- when: /'(?:[^'\\\r\n]|\\.)*'/ tag: "T_STRING" highlight: "string"
|
|
63
63
|
string3 ->
|
|
64
|
-
- when: /`(?:[^`\\]|\\.)*`/ tag: "T_STRING"
|
|
64
|
+
- when: /`(?:[^`\\]|\\.)*`/ tag: "T_STRING" highlight: "string"
|
|
65
65
|
regex ->
|
|
66
|
-
- when: /\/(?:[^\/\\\r\n]|\\.)+\// tag: "T_REGEX"
|
|
66
|
+
- when: /\/(?:[^\/\\\r\n]|\\.)+\// tag: "T_REGEX" highlight: "regexp"
|
|
67
67
|
integer ->
|
|
68
|
-
- when: /\d+/ tag: "T_INTEGER"
|
|
68
|
+
- when: /\d+/ tag: "T_INTEGER" highlight: "number"
|
|
69
69
|
word ->
|
|
70
70
|
- when: /[a-zA-Z_][a-zA-Z_\d]*/ tag: "T_WORD"
|
|
71
71
|
ws ->
|
|
72
72
|
- when: /\s+/ tag: "T_WS"
|
|
73
73
|
l_colon ->
|
|
74
|
-
- when: ":" tag: "L_COLON"
|
|
74
|
+
- when: ":" tag: "L_COLON" highlight: "keyword"
|
|
75
75
|
l_scolon ->
|
|
76
76
|
- when: ";" tag: "L_SCOLON"
|
|
77
77
|
l_qmark ->
|
|
@@ -83,7 +83,7 @@ lexer: {{
|
|
|
83
83
|
l_comma ->
|
|
84
84
|
- when: "," tag: "L_COMMA"
|
|
85
85
|
l_pipe ->
|
|
86
|
-
- when: "|" tag: "L_PIPE"
|
|
86
|
+
- when: "|" tag: "L_PIPE" highlight: "keyword"
|
|
87
87
|
l_parenl ->
|
|
88
88
|
- when: "(" tag: "L_PARENL"
|
|
89
89
|
l_parenr ->
|
|
@@ -93,15 +93,15 @@ lexer: {{
|
|
|
93
93
|
l_templater ->
|
|
94
94
|
- when: "}}" tag: "L_TEMPLATER"
|
|
95
95
|
l_arrow ->
|
|
96
|
-
- when: "->" tag: "L_ARROW"
|
|
96
|
+
- when: "->" tag: "L_ARROW" highlight: "keyword"
|
|
97
97
|
l_dsign ->
|
|
98
98
|
- when: "$" tag: "L_DSIGN"
|
|
99
99
|
l_dash ->
|
|
100
100
|
- when: "-" tag: "L_DASH"
|
|
101
101
|
comment ->
|
|
102
|
-
- when: /\/\/[^\n]*/ tag: "T_COMMENT"
|
|
102
|
+
- when: /\/\/[^\n]*/ tag: "T_COMMENT" highlight: "comment"
|
|
103
103
|
commentmulti ->
|
|
104
|
-
- when: /\/\*.*\*\// tag: "T_COMMENT"
|
|
104
|
+
- when: /\/\*.*\*\// tag: "T_COMMENT" highlight: "comment"
|
|
105
105
|
|
|
106
106
|
}}
|
|
107
107
|
|
|
@@ -162,6 +162,7 @@ grammar: {{
|
|
|
162
162
|
| K_POP : {{ { pop: 1 } }}
|
|
163
163
|
| K_POP _ L_COLON _ T_INTEGER : {{ { pop: parseInt($4) } }}
|
|
164
164
|
| K_POP _ L_COLON _ K_ALL : {{ { pop: "all" } }}
|
|
165
|
+
| K_HIGHLIGHT _ L_COLON _ T_STRING : {{ { highlight: $4 } }}
|
|
165
166
|
| K_INSET : {{ { inset: 1 } }}
|
|
166
167
|
| K_INSET _ L_COLON _ T_INTEGER : {{ { inset: parseInt($4) } }}
|
|
167
168
|
| K_SET _ L_COLON _ T_WORD : {{ { set: $4 } }}
|
|
@@ -257,6 +258,7 @@ grammar: {{
|
|
|
257
258
|
K_TYPE -> "type"
|
|
258
259
|
K_WHEN -> "when"
|
|
259
260
|
K_POP -> "pop"
|
|
261
|
+
K_HIGHLIGHT -> "highlight"
|
|
260
262
|
K_INSET -> "inset"
|
|
261
263
|
K_SET -> "set"
|
|
262
264
|
K_GOTO -> "goto"
|