1
+ import * as fromMem from "@peggyjs/from-mem" ;
1
2
import * as path from "path" ;
2
3
import * as peggy from "peggy" ;
3
- import * as util from "node-inspect-extracted" ;
4
4
import {
5
5
ExtensionContext ,
6
6
OutputChannel ,
@@ -12,6 +12,7 @@ import {
12
12
} from "vscode" ;
13
13
import { MemFS } from "../vendor/vscode-extension-samples/fileSystemProvider" ;
14
14
import { debounce } from "../common/debounce" ;
15
+ import { fileURLToPath } from "url" ;
15
16
16
17
const PEGGY_INPUT_SCHEME = "peggyjsin" ;
17
18
@@ -22,60 +23,98 @@ interface GrammarConfig {
22
23
grammar_uri : Uri ;
23
24
input_uri : Uri ;
24
25
timeout ?: NodeJS . Timeout ;
25
- grammar_text ?: string ;
26
- parser ?: any ;
27
26
}
28
27
29
28
async function executeAndDisplayResults (
30
29
output : OutputChannel ,
31
30
config : GrammarConfig
32
31
) : Promise < void > {
33
32
output . show ( true ) ;
34
- let out = `// ${ config . name } ${ config . start_rule ? `(${ config . start_rule } )` : "" } \n` ;
33
+ let out = `// ${ config . name } ${ config . start_rule ? ` (${ config . start_rule } )` : "" } \n` ;
34
+
35
+ const [ grammar_document , input_document ] = [
36
+ await workspace . openTextDocument ( config . grammar_uri ) ,
37
+ await workspace . openTextDocument ( config . input_uri ) ,
38
+ ] ;
39
+
40
+ // Never leave it dirty; it's saved in memory anyway.
41
+ // Don't bother to wait for the promise.
42
+ input_document . save ( ) ;
43
+ const input = input_document . getText ( ) ;
44
+ const filename = fileURLToPath ( grammar_document . uri . toString ( ) ) ;
35
45
36
46
try {
37
- const [ grammar_document , input_document ] = [
38
- await workspace . openTextDocument ( config . grammar_uri ) ,
39
- await workspace . openTextDocument ( config . input_uri ) ,
40
- ] ;
41
-
42
- // Never leave it dirty; it's saved in memory anyway.
43
- // Don't bother to wait for the promise.
44
- input_document . save ( ) ;
45
47
const grammar_text = grammar_document . getText ( ) ;
46
48
47
- if ( grammar_text !== config . grammar_text ) {
48
- config . parser = peggy . generate (
49
- grammar_text ,
50
- config . start_rule
51
- ? {
52
- allowedStartRules : [ config . start_rule ] ,
53
- }
54
- : undefined
55
- ) ;
56
- config . grammar_text = grammar_text ;
49
+ const format = await fromMem . guessModuleType ( filename ) ;
50
+ const pbo : peggy . SourceBuildOptions < "source" > = {
51
+ output : "source" ,
52
+ format,
53
+ } ;
54
+ if ( config . start_rule ) {
55
+ pbo . allowedStartRules = [ config . start_rule ] ;
57
56
}
57
+ const parserSource = peggy . generate ( grammar_text , pbo ) ;
58
58
59
- const input = input_document . getText ( ) ;
60
- const result = config . parser . parse (
61
- input ,
62
- config . start_rule ? { startRule : config . start_rule } : undefined
63
- ) ;
59
+ const consoleOutput : fromMem . ConsoleOutErr = { } ;
60
+ const parseOpts : PEG . ParserOptions = {
61
+ grammarSource : config . name ,
62
+ } ;
63
+ if ( config . start_rule ) {
64
+ parseOpts . startRule = config . start_rule ;
65
+ }
64
66
65
- out += util . inspect ( result , {
66
- depth : Infinity ,
67
- colors : false ,
68
- maxArrayLength : Infinity ,
69
- maxStringLength : Infinity ,
70
- breakLength : 40 ,
71
- sorted : true ,
67
+ const result = await fromMem ( parserSource , {
68
+ filename,
69
+ format,
70
+ consoleOutput,
71
+ exec : `
72
+ const util = await import("node:util");
73
+ try {
74
+ const res = IMPORTED.parse(...arg);
75
+ return util.inspect(res, {
76
+ depth: Infinity,
77
+ colors: false,
78
+ maxArrayLength: Infinity,
79
+ maxStringLength: Infinity,
80
+ breakLength: 40,
81
+ sorted: true,
82
+ });
83
+ } catch (er) {
84
+ if (typeof er.format === "function") {
85
+ er.message = er.format([{
86
+ source: arg[1].grammarSource,
87
+ text: arg[0],
88
+ }]);
89
+ }
90
+ throw er;
91
+ }
92
+ ` ,
93
+ arg : [ input , parseOpts ] ,
94
+ colorMode : false ,
72
95
} ) ;
96
+
97
+ consoleOutput . capture ?.( ) ;
98
+ if ( consoleOutput . out ) {
99
+ consoleOutput . out = consoleOutput . out . trimEnd ( ) ;
100
+ out += "\n" + consoleOutput . out . replace ( / ^ / gm, "// stdout: " ) + "\n" ;
101
+ }
102
+ if ( consoleOutput . err ) {
103
+ consoleOutput . err = consoleOutput . err . trimEnd ( ) ;
104
+ out += "\n" + consoleOutput . err . replace ( / ^ / gm, "// stderr: " ) + "\n" ;
105
+ }
73
106
out += "\n" ;
74
- } catch ( error ) {
107
+ out += result ;
108
+ out += "\n" ;
109
+ } catch ( error ) {
75
110
out += error . toString ( ) ;
111
+ }
112
+ if ( ! out . endsWith ( "\n" ) ) {
76
113
out += "\n" ;
77
114
}
78
- // Replace once, since addLine causes issues with trailing spaces.
115
+
116
+ // Replace once. Causes trailing spaces to be deleted in input doc,
117
+ // seemingly.
79
118
output . replace ( out ) ;
80
119
}
81
120
@@ -93,10 +132,10 @@ export function activate(context: ExtensionContext): void {
93
132
. replace ( / ^ [ ( ] [ ^ ) ] + [ ) ] _ _ / , "" ) ;
94
133
}
95
134
96
- function trackGrammar (
135
+ async function trackGrammar (
97
136
grammar_document_uri : Uri ,
98
137
start_rule ?: string
99
- ) : GrammarConfig {
138
+ ) : Promise < GrammarConfig > {
100
139
const grammar_name = grammarNameFromUri ( grammar_document_uri ) ;
101
140
const key = `${ grammar_name } :${ start_rule || "*" } ` ;
102
141
@@ -109,11 +148,10 @@ export function activate(context: ExtensionContext): void {
109
148
) ;
110
149
111
150
if ( ! is_input_document_open ) {
112
- workspace . fs . writeFile ( input_document_uri , Buffer . from ( "" ) ) . then ( ( ) => {
113
- window . showTextDocument ( input_document_uri , {
114
- viewColumn : ViewColumn . Beside ,
115
- preserveFocus : true ,
116
- } ) ;
151
+ await workspace . fs . writeFile ( input_document_uri , Buffer . from ( "" ) ) ;
152
+ await window . showTextDocument ( input_document_uri , {
153
+ viewColumn : ViewColumn . Beside ,
154
+ preserveFocus : false ,
117
155
} ) ;
118
156
}
119
157
const config = {
@@ -135,7 +173,7 @@ export function activate(context: ExtensionContext): void {
135
173
config . grammar_uri . toString ( ) === document_uri_string
136
174
|| config . input_uri . toString ( ) === document_uri_string
137
175
) {
138
- await executeAndDisplayResults ( peggy_output , config ) ;
176
+ debounceExecution ( peggy_output , config ) ;
139
177
}
140
178
}
141
179
} ) ;
@@ -154,19 +192,22 @@ export function activate(context: ExtensionContext): void {
154
192
documents_changed ,
155
193
documents_closed ,
156
194
peggy_output ,
157
- commands . registerTextEditorCommand ( "editor.peggyLive" , editor => {
158
- const grammar_config = trackGrammar ( editor . document . uri ) ;
195
+ commands . registerTextEditorCommand ( "editor.peggyLive" , async editor => {
196
+ const grammar_config = await trackGrammar ( editor . document . uri ) ;
159
197
debounceExecution ( peggy_output , grammar_config ) ;
160
198
} ) ,
161
- commands . registerTextEditorCommand ( "editor.peggyLiveFromRule" , editor => {
199
+ commands . registerTextEditorCommand ( "editor.peggyLiveFromRule" , async editor => {
162
200
const word_range = editor . document . getWordRangeAtPosition (
163
201
editor . selection . start ,
164
- / [ _ $ a - z A - Z \xA0 - \uFFFF ] [ _ $ a - z A - Z 0 - 9 \xA0 - \uFFFF ] * /
202
+ / [ \p { ID_Start } ] [ \p { ID_Continue } ] * / u
165
203
) ;
166
204
167
205
if ( word_range !== null ) {
168
206
const rule_name = editor . document . getText ( word_range ) ;
169
- const grammar_config = trackGrammar ( editor . document . uri , rule_name ) ;
207
+ const grammar_config = await trackGrammar (
208
+ editor . document . uri ,
209
+ rule_name
210
+ ) ;
170
211
171
212
debounceExecution ( peggy_output , grammar_config ) ;
172
213
}
0 commit comments