Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions dev/index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body class="replit-ui-theme-root dark">
<div id="editor"></div>
<script type="module" src="./index.ts"></script>
</body>
</html>

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>

<body class="replit-ui-theme-root dark">
<div id="editor"></div>
<script type="module" src="./index.ts"></script>
</body>

</html>
5 changes: 3 additions & 2 deletions dev/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EditorState } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { basicSetup } from 'codemirror';
import { indentUnit } from "@codemirror/language";
import { csharp, parser } from "../dist/";
import { printTree } from "./print-lezer-tree";
import { oneDark } from '@codemirror/theme-one-dark';
Expand Down Expand Up @@ -232,9 +233,9 @@ A.B c = 1;
new EditorView({
state: EditorState.create({
doc,
extensions: [basicSetup, csharp(), oneDark, EditorView.lineWrapping],
extensions: [basicSetup, csharp(), oneDark, indentUnit.of(" "), EditorView.lineWrapping],
}),
parent: document.querySelector('#editor'),
parent: document.querySelector('#editor')!,
});

console.log(printTree(parser.parse(doc), doc));
14 changes: 7 additions & 7 deletions dev/print-lezer-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Text } from "@codemirror/state"
import { Input, NodeType, SyntaxNode, Tree, TreeCursor } from "@lezer/common"

class StringInput implements Input {
constructor(private readonly input: string) {}
constructor(private readonly input: string) { }

get length() {
return this.input.length
Expand Down Expand Up @@ -66,7 +66,7 @@ export function traverseTree(
}: TreeTraversalOptions,
): void {
if (!(cursor instanceof TreeCursor)) cursor = cursor.cursor()
for (;;) {
for (; ;) {
let node = cursorNode(cursor)
let leave = false
if (node.from <= to && node.to >= from) {
Expand All @@ -79,7 +79,7 @@ export function traverseTree(
}
if (!node.isLeaf) continue
}
for (;;) {
for (; ;) {
node = cursorNode(cursor, node.isLeaf)
if (leave && onLeave) if (onLeave(node) === false) return
leave = cursor.type.isAnonymous
Expand Down Expand Up @@ -196,10 +196,10 @@ export function printTree(
" " +
(hasRange
? "[" +
colorize(locAt(text, start + node.from), Color.Yellow) +
".." +
colorize(locAt(text, start + node.to), Color.Yellow) +
"]"
colorize(locAt(text, start + node.from), Color.Yellow) +
".." +
colorize(locAt(text, start + node.to), Color.Yellow) +
"]"
: colorize(locAt(text, start + node.from), Color.Yellow))
if (hasRange && node.isLeaf) {
state.output += ": " + colorize(JSON.stringify(inp.read(node.from, node.to)), Color.Green)
Expand Down
7 changes: 4 additions & 3 deletions dev/watch.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const {watch} = require("@codemirror/buildhelper")
const {resolve} = require("path")
const { watch } = require("@marijn/buildtool")
const { resolve } = require("path")
const { options } = require("@codemirror/buildhelper/src/options")

let args = process.argv.slice(2)

Expand All @@ -10,4 +11,4 @@ if (args.length != 1) {
process.exit(1)
}

watch([resolve(args[0])])
watch([resolve(args[0])], [], options)
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
},
"devDependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/buildhelper": "^0.1.16",
"@codemirror/buildhelper": "^1.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/theme-one-dark": "^6.0.0",
Expand All @@ -45,8 +45,8 @@
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"codemirror": "^6.0.0",
"npm-run-all": "^4.1.5",
"vite": "^2.3.8"
"npm-run-all": "^4.0.0",
"vite": "^7.0.0"
},
"repository": {
"type": "git",
Expand Down
95 changes: 78 additions & 17 deletions src/syntax.grammar
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@
| verbatimString
}

regularString { '"' regularStringCharacter* '"' 'u8'? }
regularString { '"' regularStringCharacter* '"' ('U8' | 'u8')? }

regularStringCharacter
{ singleRegularStringCharacter
Expand All @@ -165,7 +165,7 @@

singleRegularStringCharacter { !["\\\r\n\u0085\u2028\u2029] }

verbatimString { '@"' verbatimStringCharacter* '"' 'u8'? }
verbatimString { '@"' verbatimStringCharacter* '"' ('U8' | 'u8')? }

verbatimStringCharacter
{ !["]
Expand Down Expand Up @@ -200,6 +200,10 @@
| pp_diagnostic
| pp_region
| pp_pragma
| pp_load
| pp_nullable
| pp_reference
| pp_custom
}

pp_declaration
Expand Down Expand Up @@ -229,6 +233,13 @@

pp_pragma { 'pragma' (whitespace+ ![\n]+)? }

pp_load { 'load' (whitespace+ ![\n]+)? }

pp_nullable { 'nullable' (whitespace+ ![\n]+)? }

pp_reference { 'r' (whitespace+ ![\n]+)? }

pp_custom { identifier (whitespace+ ![\n]+)? }

// Precedence

Expand Down Expand Up @@ -405,6 +416,7 @@ primaryNoArrayCreationExpr
| checkedExpr
| uncheckedExpr
| defaultValueExpr
| fieldExpr
| nameofExpr
| switchExpr
| withExpr
Expand Down Expand Up @@ -621,6 +633,11 @@ uncheckedExpr { kw<"unchecked"> delim<'(' expr ')'> }
defaultValueExpr { kw<"default"> ~default delim<'(' type ')'> }


// Field expr

fieldExpr { kw<"field"> ~field }


// Nameof expr

nameofExpr { kw<"nameof"> delim<'(' namedEntity ')'> }
Expand Down Expand Up @@ -1230,6 +1247,7 @@ namespaceMemberDecl { namespaceDecl | typeDecl }

typeDecl
{ classDecl
| extensionBlockDecl
| structDecl
| interfaceDecl
| recordDecl
Expand Down Expand Up @@ -1279,34 +1297,48 @@ typeParam { TypeIdentifier }

// Type parameter constraints

typeParamConstraintsClause { kw<"where"> typeParam ':' typeParamConstraints }
typeParamConstraintsClause { kw<"where"> typeParam ':' csep1<typeParamConstraints> }

typeParamConstraints
{ csep1<primaryConstraint> (',' ctorConstraint)?
{ allowsConstraintClause
| classOrStructConstraint
| ctorConstraint
| defaultConstraint
| primaryConstraint
}

allowsConstraintClause { kw<"allows"> csep1<allowsConstraint> }

allowsConstraint { refStructConstraint }

refStructConstraint { kw<"ref"> kw<"struct"> }

classOrStructConstraint
{ kw<"class"> '?'?
| kw<"struct"> '?'?
}

ctorConstraint { new '(' ')' }

defaultConstraint { kw<"default"> }

primaryConstraint
{ typeName '?'?
| kw<"class"> '?'?
| kw<"struct">
| kw<"notnull">
| kw<"default">
| kw<"unmanaged">
}

ctorConstraint { new '(' ')' }


// Class declaration

classDecl {
attrs? modifier* kw<"class">
TypeIdentifier typeParamList? classBase? typeParamConstraintsClause*
classBody ';'?
TypeIdentifier typeParamList? typeParamConstraintsClause*
formalParams? classBase?
(classBody ';'? | ';')
}

classBase { ':' csep1<typeName> }
classBase { ':' csep1<typeName> arguments? (',' typeName)* }

classBody { delim<'{' classMemberDecl* '}'> }

Expand All @@ -1324,6 +1356,32 @@ classMemberDecl
}


// Extension Block declaration


extensionBlockDecl {
attrs? modifier* kw<"extension">
typeParamList? typeParamConstraintsClause*
formalParams typeParamConstraintsClause*
extensionBlockBody ';'?
}

extensionBlockBody { delim<'{' extensionBlockMemberDecl* '}'> }

extensionBlockMemberDecl
{ constantDecl
| fieldDecl
| methodDecl
| propertyDecl
| eventDecl
| indexerDecl
| operatorDecl
| ctorDecl
| finalizerDecl
| typeDecl
}


// Constant declaration

constantDecl {
Expand Down Expand Up @@ -1549,8 +1607,9 @@ finalizerBody

structDecl {
attrs? modifier* kw<"struct">
TypeIdentifier typeParamList? classBase? typeParamConstraintsClause*
structBody ';'?
TypeIdentifier typeParamList? typeParamConstraintsClause*
formalParams? classBase?
(structBody ';'? | ';')
}

structBody { delim<'{' structMemberDecl* '}'> }
Expand Down Expand Up @@ -1591,8 +1650,9 @@ stackallocInit

interfaceDecl {
attrs? modifier* kw<"interface">
TypeIdentifier variantTypeParamList? classBase? typeParamConstraintsClause*
interfaceBody ';'?
TypeIdentifier variantTypeParamList? typeParamConstraintsClause*
formalParams? classBase?
(interfaceBody ';'? | ';')
}

variantTypeParamList { '<' csep1<variantTypeParam> '>' }
Expand Down Expand Up @@ -1665,7 +1725,8 @@ recordBase {
// Enum declaration

enumDecl {
attrs? modifier* kw<"enum"> TypeIdentifier enumBase? enumBody
attrs? modifier* kw<"enum"> TypeIdentifier enumBase?
(enumBody ';'? | ';')
}

enumBase { ':' (SimpleType | typeName) }
Expand Down
30 changes: 15 additions & 15 deletions src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,31 @@ const
braceR = 125;

export const interpString = new ExternalTokenizer((input) => {
for(let i = 0; ; i++) {
switch(input.next) {
for (let i = 0; ; i++) {
switch (input.next) {
case -1:
if(i > 0) input.acceptToken(interpStringContent);
if (i > 0) input.acceptToken(interpStringContent);
return;

case quote:
if(i > 0) input.acceptToken(interpStringContent);
if (i > 0) input.acceptToken(interpStringContent);
else input.acceptToken(interpStringEnd, 1);
return;

case braceL:
if(input.peek(1) === braceL) input.acceptToken(interpStringContent, 2)
if (input.peek(1) === braceL) input.acceptToken(interpStringContent, 2)
else input.acceptToken(interpStringBrace);
return;

case braceR:
if(input.peek(1) === braceR) input.acceptToken(interpStringContent, 2)
if (input.peek(1) === braceR) input.acceptToken(interpStringContent, 2)
return;

case backslash:
const next = input.peek(1);
if(next === braceL || next === braceR) return;
if (next === braceL || next === braceR) return;
input.advance();
// FALLTHROUGH
// FALLTHROUGH

default:
input.advance();
Expand All @@ -48,25 +48,25 @@ export const interpString = new ExternalTokenizer((input) => {
});

export const interpVString = new ExternalTokenizer((input) => {
for(let i = 0; ; i++) {
switch(input.next) {
for (let i = 0; ; i++) {
switch (input.next) {
case -1:
if(i > 0) input.acceptToken(interpVStringContent);
if (i > 0) input.acceptToken(interpVStringContent);
return;

case quote:
if(input.peek(1) === quote) input.acceptToken(interpVStringContent, 2)
else if(i > 0) input.acceptToken(interpVStringContent)
if (input.peek(1) === quote) input.acceptToken(interpVStringContent, 2)
else if (i > 0) input.acceptToken(interpVStringContent)
else input.acceptToken(interpVStringEnd, 1);
return;

case braceL:
if(input.peek(1) === braceL) input.acceptToken(interpVStringContent, 2)
if (input.peek(1) === braceL) input.acceptToken(interpVStringContent, 2)
else input.acceptToken(interpVStringBrace);
return;

case braceR:
if(input.peek(1) === braceR) input.acceptToken(interpVStringContent, 2)
if (input.peek(1) === braceR) input.acceptToken(interpVStringContent, 2)
return;

default:
Expand Down
Loading