Add automatic syntax checker, fix editor bugs

This commit is contained in:
Nilay Majorwar
2022-01-22 21:22:38 +05:30
parent dbccab5244
commit 94dce5bfa9
12 changed files with 163 additions and 15 deletions

View File

@ -28,6 +28,10 @@ export default class BrainfuckLanguageEngine implements LanguageEngine<BFRS> {
this._pc = DEFAULT_PC;
}
validateCode(code: string) {
this.parseCode(code);
}
prepare(code: string, input: string) {
this._input = input;
this._ast = this.parseCode(code);

View File

@ -36,6 +36,10 @@ export default class ChefLanguageEngine implements LanguageEngine<T.ChefRS> {
this._input = DEFAULT_INPUT();
}
validateCode(code: string) {
parseProgram(code);
}
prepare(code: string, input: string) {
this._ast = parseProgram(code);
this._input = new InputStream(input);

View File

@ -21,6 +21,10 @@ export default class DeadfishLanguageEngine implements LanguageEngine<DFRS> {
this._pc = DEFAULT_PC;
}
validateCode(code: string) {
this.parseCode(code);
}
prepare(code: string, _input: string) {
this._ast = this.parseCode(code);
}

View File

@ -1,6 +1,8 @@
import { LanguageEngine, StepExecutionResult } from "./types";
import {
isParseError,
isRuntimeError,
serializeParseError,
serializeRuntimeError,
WorkerRuntimeError,
} from "./worker-errors";
@ -58,6 +60,19 @@ class ExecutionController<RS> {
this._breakpoints = points;
}
/**
* Validate the syntax of the given code
* @param code Code content, lines separated by '\n'
*/
validateCode(code: string) {
try {
this._engine.validateCode(code);
} catch (error) {
if (isParseError(error)) return serializeParseError(error);
else throw error;
}
}
/**
* Pause the ongoing execution.
* - If already paused, returns immediately

View File

@ -13,6 +13,11 @@ const ackMessage = <RS, A extends C.WorkerAckType>(
error,
});
/** Create a worker response for code validation result */
const validationMessage = <RS, A extends C.WorkerAckType>(
error?: E.WorkerParseError
): C.WorkerResponseData<RS, A> => ({ type: "validate", error });
/** Create a worker response for execution result */
const resultMessage = <RS, A extends C.WorkerAckType>(
result: StepExecutionResult<RS>,
@ -72,6 +77,15 @@ const updateBreakpoints = <RS>(
postMessage(ackMessage("bp-update"));
};
/** Validate the user's program syntax */
const validateCode = <RS>(
controller: ExecutionController<RS>,
code: string
) => {
const error = controller.validateCode(code);
postMessage(validationMessage(error));
};
/**
* Execute the entire program loaded on engine,
* and return result of execution.
@ -112,6 +126,8 @@ export const setupWorker = <RS>(engine: LanguageEngine<RS>) => {
if (ev.data.type === "Reset") return resetController(controller);
if (ev.data.type === "Prepare")
return prepare(controller, ev.data.params);
if (ev.data.type === "ValidateCode")
return validateCode(controller, ev.data.params.code);
if (ev.data.type === "Execute")
return execute(controller, ev.data.params.interval);
if (ev.data.type === "Pause") return await pauseExecution(controller);

View File

@ -45,6 +45,9 @@ export type StepExecutionResult<RS> = {
* execution and debugging API to the platform.
*/
export interface LanguageEngine<RS> {
/** Validate the syntax of the given code. Throw ParseError if any */
validateCode: (code: string) => void;
/** Load code and user input into the engine and prepare for execution */
prepare: (code: string, input: string) => void;

View File

@ -1,4 +1,4 @@
import { DocumentRange, StepExecutionResult } from "./types";
import { StepExecutionResult } from "./types";
import * as E from "./worker-errors";
/** Types of requests the worker handles */
@ -19,6 +19,10 @@ export type WorkerRequestData =
type: "UpdateBreakpoints";
params: { points: number[] };
}
| {
type: "ValidateCode";
params: { code: string };
}
| {
type: "Execute";
params: { interval: number };
@ -57,6 +61,11 @@ export type WorkerResponseData<RS, A extends WorkerAckType> =
data: A;
error?: WorkerAckError[A];
}
/** Result of code validation, containing parsing error (if any) */
| {
type: "validate";
error?: E.WorkerParseError;
}
/** Response containing step execution result, and runtime error (if any) */
| {
type: "result";