Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions langium-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"fileExtensions": [".lox"],
"textMate": {
"out": "syntaxes/lox.tmLanguage.json"
},
"monarch": {
"out": "syntaxes/lox.monarch.ts"
}
}],
"out": "src/language-server/generated"
Expand Down
184 changes: 155 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@
"build": "tsc -b tsconfig.json",
"watch": "tsc -b tsconfig.json --watch",
"lint": "eslint src --ext ts",
"clean": "rimraf out && rimraf node_modules",
"langium:generate": "langium generate",
"langium:watch": "langium generate --watch"
},
"dependencies": {
"chevrotain": "^9.1.0",
"colors": "^1.4.0",
"commander": "^8.0.0",
"langium": "1.0.1",
"langium": "~1.2.1",
"uuid": "^9.0.0",
"vscode-languageclient": "8.0.2",
"vscode-languageserver": "8.0.2",
Expand Down
4 changes: 2 additions & 2 deletions src/interpreter/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { BinaryExpression, Expression, isBinaryExpression, isBooleanExpression,
import { createLoxServices } from "../language-server/lox-module";
import { v4 } from 'uuid';
import { URI } from "vscode-uri";
import { CancellationToken } from "vscode-languageclient";
import { CancellationToken } from "vscode-languageserver/browser";

export interface InterpreterContext {
log: (value: unknown) => MaybePromise<void>
Expand Down Expand Up @@ -88,7 +88,7 @@ async function buildDocument(program: string): Promise<BuildResult> {
}
}

async function runProgram(program: LoxProgram, outerContext: InterpreterContext): Promise<void> {
export async function runProgram(program: LoxProgram, outerContext: InterpreterContext): Promise<void> {
const context: RunnerContext = {
variables: new Variables(),
log: outerContext.log
Expand Down
51 changes: 51 additions & 0 deletions src/language-server/main-browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/******************************************************************************
* Copyright 2022 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/

import { startLanguageServer, EmptyFileSystem, DocumentState, LangiumDocument } from 'langium';
import { BrowserMessageReader, BrowserMessageWriter, Diagnostic, NotificationType, createConnection } from 'vscode-languageserver/browser';
import { createLoxServices } from './lox-module';
import { runInterpreter } from '../interpreter/runner';

declare const self: DedicatedWorkerGlobalScope;

/* browser specific setup code */
const messageReader = new BrowserMessageReader(self);
const messageWriter = new BrowserMessageWriter(self);

const connection = createConnection(messageReader, messageWriter);

// Inject the shared services and language-specific services
const { shared } = createLoxServices({ connection, ...EmptyFileSystem });

// Start the language server with the shared services
startLanguageServer(shared);

// Send a notification with the serialized AST after every document change
type DocumentChange = { uri: string, content: string, diagnostics: Diagnostic[] };
const documentChangeNotification = new NotificationType<DocumentChange>('browser/DocumentChange');
shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated, documents => {
for (const document of documents) {
if (document.diagnostics === undefined || document.diagnostics.filter((i) => i.severity === 1).length === 0) {
sendMessage(document, "notification", "startInterpreter")
runInterpreter(document.textDocument.getText(), {
log: (message) => {
sendMessage(document, "output", message)
}
})
}
else {
sendMessage(document, "error", document.diagnostics)
}
}
});

function sendMessage(document: LangiumDocument, type: string, content: unknown): void {
connection.sendNotification(documentChangeNotification, {
uri: document.uri.toString(),
content: JSON.stringify({ type, content }),
diagnostics: document.diagnostics ?? []
});
}
30 changes: 30 additions & 0 deletions syntaxes/lox.monarch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Monarch syntax highlighting for the lox language.
export default {
keywords: [
'and','boolean','class','else','false','for','fun','if','nil','number','or','print','return','string','super','this','true','var','void','while'
],
operators: [
'!','!=','*','+',',','-','.','/',':',';','<','<=','=','==','=>','>','>='
],
symbols: /!|!=|\(|\)|\*|\+|,|-|\.|/|:|;|<|<=|=|==|=>|>|>=|\{|\}/,

tokenizer: {
initial: [
{ regex: /[_a-zA-Z][\w_]*/, action: { cases: { '@keywords': {"token":"keyword"}, '@default': {"token":"ID"} }} },
{ regex: /[0-9]+(\.[0-9]+)?/, action: {"token":"number"} },
{ regex: /"[^"]*"/, action: {"token":"string"} },
{ include: '@whitespace' },
{ regex: /@symbols/, action: { cases: { '@operators': {"token":"operator"}, '@default': {"token":""} }} },
],
whitespace: [
{ regex: /\s+/, action: {"token":"white"} },
{ regex: /\/\*/, action: {"token":"comment","next":"@comment"} },
{ regex: /\/\/[^\n\r]*/, action: {"token":"comment"} },
],
comment: [
{ regex: /[^\/\*]+/, action: {"token":"comment"} },
{ regex: /\*\//, action: {"token":"comment","next":"@pop"} },
{ regex: /[\/\*]/, action: {"token":"comment"} },
],
}
};
Loading