Skip to content

Commit 79a2d75

Browse files
committed
Fix "Top-level statements"
Add pp_ignored and pp_shebang
1 parent 129a961 commit 79a2d75

6 files changed

Lines changed: 123 additions & 20 deletions

File tree

.github/workflows/build-and-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
registry: https://www.myget.org/F/where/npm
4141

4242
- name: Upload Pages artifact
43-
uses: actions/upload-pages-artifact@v4
43+
uses: actions/upload-pages-artifact@v5
4444
with:
4545
path: dev/dist
4646

dev/index.ts

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,16 @@ import { indentWithTab } from '@codemirror/commands';
66
import { csharp, parser } from '../dist/';
77
import { printTree } from './print-lezer-tree';
88
import { oneDark } from '@codemirror/theme-one-dark';
9+
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string';
910

10-
const doc = /*`using System;
11+
function getCodeFromHash() {
12+
const hash = location.hash.substring(1);
13+
if (hash) {
14+
return decompressFromEncodedURIComponent(hash);
15+
}
16+
}
17+
18+
const doc = getCodeFromHash() || /*`using System;
1119
using System.Reflection;
1220
1321
public sealed class InterrogateHelpUrls
@@ -236,24 +244,56 @@ namespace osu.Game.Rulesets
236244
const syntax = document.createElement('pre');
237245
syntax.className = 'ͼo';
238246
document.getElementById('syntax')!.appendChild(syntax);
247+
function setTimeoutAsync(timeout?: number) {
248+
return new Promise<void>(resolve => setTimeout(resolve, timeout));
249+
}
239250

240-
new EditorView({
251+
let count = -1;
252+
let hashChanged = false;
253+
const editor = new EditorView({
241254
state: EditorState.create({
242-
doc,
255+
doc: doc,
243256
extensions: [
244257
basicSetup,
245258
csharp(),
246259
oneDark,
247260
keymap.of([indentWithTab]),
248261
indentUnit.of(' '),
249-
EditorView.updateListener.of(e => {
262+
EditorView.updateListener.of(async e => {
250263
if (e.docChanged) {
251-
const doc = e.state.doc.toString();
252-
syntax.textContent = printTree(parser.parse(doc), doc);
264+
try {
265+
count++;
266+
const doc = e.state.doc.toString();
267+
syntax.textContent = printTree(parser.parse(doc), doc);
268+
await setTimeoutAsync(500);
269+
if (count != 0) { return; }
270+
location.hash = compressToEncodedURIComponent(doc);
271+
hashChanged = true;
272+
}
273+
finally {
274+
count--;
275+
}
253276
}
254-
})],
277+
})
278+
],
255279
}),
256280
parent: document.querySelector('#editor')!,
257281
});
258282

259283
syntax.textContent = printTree(parser.parse(doc), doc);
284+
addEventListener('hashchange', () => {
285+
if (hashChanged) {
286+
hashChanged = false;
287+
return;
288+
}
289+
const code = getCodeFromHash();
290+
if (code) {
291+
editor.dispatch({
292+
changes: {
293+
from: 0,
294+
to: editor.state.doc.length,
295+
insert: code
296+
}
297+
});
298+
}
299+
});

dev/print-lezer-tree.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,11 @@ export function printTree(
183183
if (hasPrefix) {
184184
state.output += (!isTop ? "\n" : "") + state.prefixes.join("")
185185
if (state.hasNextSibling) {
186-
state.output += " ├ "
187-
state.prefixes.push(" │ ")
186+
state.output += " ├ "
187+
state.prefixes.push(" │")
188188
} else {
189-
state.output += " └ "
190-
state.prefixes.push(" ")
189+
state.output += " └ "
190+
state.prefixes.push(" ")
191191
}
192192
}
193193
const hasRange = node.from !== node.to

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@lezer/highlight": "^1.0.0",
4747
"@lezer/lr": "^1.0.0",
4848
"codemirror": "^6.0.0",
49+
"lz-string": "^1.0.0",
4950
"npm-run-all": "^4.0.0",
5051
"vite": "^8.0.0"
5152
},

src/syntax.grammar

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
nullcoal @right,
3434
ternary @right,
3535
params,
36+
anonMethod,
37+
topLevelLocalFunc,
3638
arrow @right,
3739
assign @right,
3840
throw @left,
@@ -198,7 +200,9 @@
198200
| pp_conditional
199201
| pp_line
200202
| pp_diagnostic
203+
| pp_ignored
201204
| pp_region
205+
| pp_shebang
202206
| pp_pragma
203207
| pp_load
204208
| pp_nullable
@@ -223,12 +227,19 @@
223227
| 'warning' (whitespace+ ![\n]+)?
224228
}
225229

230+
pp_ignored {
231+
':' ![\n]+
232+
}
226233

227234
pp_region {
228235
'region' (whitespace+ ![\n]+)?
229236
| 'endregion' (whitespace+ ![\n]+)?
230237
}
231238

239+
pp_shebang {
240+
'!' ![\n]*
241+
}
242+
232243
pp_line { 'line' whitespace+ ![\n]+ }
233244

234245
pp_pragma { 'pragma' (whitespace+ ![\n]+)? }
@@ -303,7 +314,7 @@ namespaceOrTypeName {
303314

304315

305316
type {
306-
(typeName | SimpleType | tupleType) (!typeUnary2 ~elementAccess rankSpecifier+ nullOrPtr? | nullOrPtr)
317+
(typeName | SimpleType | tupleType) (!typeUnary2 ~elementAccess rankSpecifier+ nullOrPtr? | nullOrPtr)?
307318
}
308319

309320
nonArrayType {
@@ -312,8 +323,7 @@ nonArrayType {
312323

313324
nullOrPtr {
314325
!typeUnary '*'+
315-
|
316-
!typeUnary '?'
326+
| !typeUnary '?'
317327
}
318328

319329
arrayType { nonArrayType !typeUnary2 rankSpecifier+ }
@@ -721,7 +731,7 @@ LambdaExpr[@dynamicPrecedence=1] {
721731
}
722732

723733
anonMethodExpr {
724-
kw<"async">? kw<"delegate"> explicitAnonFuncSignature? block
734+
kw<"async">? !anonMethod kw<"delegate"> explicitAnonFuncSignature? block
725735
}
726736

727737
anonFuncSignature {
@@ -913,6 +923,12 @@ stmt {
913923
| embeddedStmt
914924
}
915925

926+
topLevelStmt {
927+
topLevelLabeledStmt
928+
| topLevelDeclStmt
929+
| embeddedStmt
930+
}
931+
916932
embeddedStmt {
917933
block
918934
| emptyStmt
@@ -950,6 +966,8 @@ emptyStmt { ';' }
950966

951967
labeledStmt { identifier ':' stmt }
952968

969+
topLevelLabeledStmt { identifier ':' topLevelStmt }
970+
953971

954972
// Declaration statement
955973

@@ -959,6 +977,12 @@ declStmt {
959977
| LocalFuncDecl
960978
}
961979

980+
topLevelDeclStmt {
981+
TopLevelVarDecl
982+
| LocalConstDecl
983+
| TopLevelLocalFuncDecl
984+
}
985+
962986

963987
// Local variable declaration
964988

@@ -972,6 +996,12 @@ LocalVarDecl {
972996
| type !varDecl csep1<varDeclarator>
973997
}
974998

999+
TopLevelVarDecl {
1000+
kw<"var"> varDesignation !assign '=' expr
1001+
| kw<"var"> csep1<varDeclarator>
1002+
| type !varDecl csep1<varDeclarator>
1003+
}
1004+
9751005
varRefModifier {
9761006
scoped refReadonly?
9771007
| refReadonly
@@ -1023,6 +1053,33 @@ localFuncBody {
10231053
| '=>' ref? expr ';'
10241054
}
10251055

1056+
TopLevelLocalFuncDecl { attrs? topLevelLocalFuncHeader localFuncBody }
1057+
1058+
topLevelLocalFuncHeader {
1059+
topLevelLocalFuncModifiers?
1060+
(ref ~ref)? type MethodName
1061+
(!typeParams typeParamList)? !params formalParams
1062+
typeParamConstraintsClause*
1063+
}
1064+
1065+
topLevelLocalFuncModifiers {
1066+
topLevelLocalFuncModifierHead topLevelLocalFuncModifier*
1067+
}
1068+
1069+
topLevelLocalFuncModifierHead {
1070+
kw<"async"> !topLevelLocalFunc
1071+
| kw<"unsafe"> !topLevelLocalFunc
1072+
| kw<"static"> !topLevelLocalFunc
1073+
| kw<"extern"> !topLevelLocalFunc
1074+
}
1075+
1076+
topLevelLocalFuncModifier {
1077+
kw<"async">
1078+
| kw<"unsafe">
1079+
| kw<"static">
1080+
| kw<"extern">
1081+
}
1082+
10261083

10271084
// Expression statement
10281085

@@ -1211,7 +1268,7 @@ fixedPtrDeclarator { identifier '=' expr }
12111268
// Compilation unit
12121269

12131270
compilationUnit {
1214-
externAliasDirective* usingDirective* /*globalAttrs?*/ block* namespaceMemberDecl*
1271+
externAliasDirective* usingDirective* globalAttrs? topLevelStmt* namespaceMemberDecl*
12151272
}
12161273

12171274

@@ -1761,15 +1818,15 @@ fixedSizeBufferDeclarator { identifier delim<'[' expr ']'> }
17611818

17621819
// Attributes
17631820

1764-
/*globalAttrs { globalAttrSection+ }
1821+
globalAttrs { globalAttrSection+ }
17651822

17661823
globalAttrSection {
1767-
'[' globalAttrTargetSpecifier csep1<attr> ','? ']'
1824+
delim<'[' globalAttrTargetSpecifier csep1<attr> ','? ']'>
17681825
}
17691826

17701827
globalAttrTargetSpecifier { globalAttrTarget ':' }
17711828

1772-
globalAttrTarget { identifier }*/
1829+
globalAttrTarget { kw<"assembly"> | kw<"module"> }
17731830

17741831
attrs { attrSection+ }
17751832

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,11 @@ log-symbols@^4.1.0:
15441544
chalk "^4.1.0"
15451545
is-unicode-supported "^0.1.0"
15461546

1547+
lz-string@^1.0.0:
1548+
version "1.5.0"
1549+
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
1550+
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
1551+
15471552
magic-string@^0.30.21:
15481553
version "0.30.21"
15491554
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz"

0 commit comments

Comments
 (0)