Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modified the language server so it sends the results of the interpreter #3

Merged
merged 18 commits into from
Oct 28, 2023
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": "shx rm -rf out node_modules",
msujew marked this conversation as resolved.
Show resolved Hide resolved
"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",
emilkrebs marked this conversation as resolved.
Show resolved Hide resolved
"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";

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
64 changes: 64 additions & 0 deletions src/language-server/main-browser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/******************************************************************************
* 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, async documents => {
for (const document of documents) {
if (document.diagnostics === undefined || document.diagnostics.filter((i) => i.severity === 1).length === 0) {
sendMessage(document, "notification", "startInterpreter")
const timeoutId = setTimeout(() => {
sendMessage(document, "error", "Interpreter timed out");
}, 1000 * 60); // 1 minute
msujew marked this conversation as resolved.
Show resolved Hide resolved

await Promise.race([
runInterpreter(document.textDocument.getText(), {
log: (message) => {
sendMessage(document, "output", message);
}
}).catch((e) => {
msujew marked this conversation as resolved.
Show resolved Hide resolved
clearTimeout(timeoutId);
sendMessage(document, "error", e.message);
}).then(() => {
clearTimeout(timeoutId);
sendMessage(document, "notification", "endInterpreter");
}),
emilkrebs marked this conversation as resolved.
Show resolved Hide resolved
new Promise((resolve) => resolve(timeoutId) )
msujew marked this conversation as resolved.
Show resolved Hide resolved
]);
}
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