refactor
This commit is contained in:
116
client/src/BranFlakesExecutorVisitor.ts
Normal file
116
client/src/BranFlakesExecutorVisitor.ts
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor';
|
||||||
|
import { LoopStmtContext } from './generated/bfParser';
|
||||||
|
import { bfVisitor } from './generated/bfVisitor';
|
||||||
|
import { DiagnosticSeverity } from 'vscode-languageclient';
|
||||||
|
import { getTree } from './BranFlakesParseRunner';
|
||||||
|
|
||||||
|
export default class BranFlakesExecutorVisitor
|
||||||
|
extends AbstractParseTreeVisitor<void>
|
||||||
|
implements bfVisitor<void> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param input Input string
|
||||||
|
* @param inputPtr Input pointer to start from
|
||||||
|
*/
|
||||||
|
constructor(protected input: string = '', protected inputPtr: number = 0) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The memory cells (Can work with negative cells this way)
|
||||||
|
*/
|
||||||
|
protected cells: Map<number, number> = new Map();
|
||||||
|
protected byteArray: Int8Array = new Int8Array(30000);
|
||||||
|
/**
|
||||||
|
* Pointer
|
||||||
|
*/
|
||||||
|
protected ptr: number = 0;
|
||||||
|
/** Output string */
|
||||||
|
protected outputStrArray: string[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output string (Available only after visiting)
|
||||||
|
*/
|
||||||
|
public get outputStr() {
|
||||||
|
return this.outputStrArray.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
defaultResult() { }
|
||||||
|
/**
|
||||||
|
* Run a file
|
||||||
|
* @param text
|
||||||
|
* @param fn
|
||||||
|
* @param input
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static run(text:string,fn: string, input:string){
|
||||||
|
//get tree and issues
|
||||||
|
const { tree, issues } = getTree(text, fn);
|
||||||
|
|
||||||
|
//get only errors
|
||||||
|
const x = issues.filter(e => e.type === DiagnosticSeverity.Error);
|
||||||
|
//if any error, drop
|
||||||
|
if (x.length > 0) {
|
||||||
|
throw Error('Errors exist');
|
||||||
|
}
|
||||||
|
// make visitor
|
||||||
|
const vis = new BranFlakesExecutorVisitor(input);
|
||||||
|
|
||||||
|
//visit the tree
|
||||||
|
vis.visit(tree);
|
||||||
|
|
||||||
|
//get output
|
||||||
|
return vis.outputStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
visitLoopStmt(ctx: LoopStmtContext) {
|
||||||
|
while ((this.cells.get(this.ptr) ?? 0) !== 0) {
|
||||||
|
this.visitChildren(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitPtrLeft() {
|
||||||
|
|
||||||
|
--this.ptr;
|
||||||
|
}
|
||||||
|
visitPtrRight() {
|
||||||
|
++this.ptr;
|
||||||
|
}
|
||||||
|
visitPtrIncr() {
|
||||||
|
|
||||||
|
const val = this.cells.get(this.ptr);
|
||||||
|
if (val === undefined) {
|
||||||
|
this.cells.set(this.ptr, 1);
|
||||||
|
} else if (val === 255) {
|
||||||
|
this.cells.delete(this.ptr);
|
||||||
|
} else {
|
||||||
|
this.cells.set(this.ptr, val + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitPtrDecr() {
|
||||||
|
// console.log('down',this.ptr,this.cells);
|
||||||
|
const val = this.cells.get(this.ptr);
|
||||||
|
if (val === undefined || val === 0) {
|
||||||
|
this.cells.set(this.ptr, 255);
|
||||||
|
} else if (val === 1) {
|
||||||
|
this.cells.delete(this.ptr);
|
||||||
|
} else {
|
||||||
|
this.cells.set(this.ptr, val - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visitOutputStmt() {
|
||||||
|
const val = this.cells.get(this.ptr) ?? 0;
|
||||||
|
const str = String.fromCharCode(val);
|
||||||
|
// console.log('op',str);
|
||||||
|
this.outputStrArray.push(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitInputStmt() {
|
||||||
|
//get char
|
||||||
|
const char = this.input.charCodeAt(this.inputPtr) ?? 0;
|
||||||
|
//increment the input pointer after this
|
||||||
|
this.inputPtr++;
|
||||||
|
this.cells.set(this.ptr, char);
|
||||||
|
}
|
||||||
|
}
|
@@ -16,9 +16,9 @@ export interface TranslationError {
|
|||||||
export function getTree(str: string, fn: string) {
|
export function getTree(str: string, fn: string) {
|
||||||
const charStreams = CharStreams.fromString(str, fn);
|
const charStreams = CharStreams.fromString(str, fn);
|
||||||
const lexer = new bfLexer(charStreams);
|
const lexer = new bfLexer(charStreams);
|
||||||
// const errorListener = this.errorManager.newErrorListener();
|
|
||||||
const issues: TranslationError[] = [];
|
const issues: TranslationError[] = [];
|
||||||
// remove the error listener. We want to put our own
|
// remove the error listener. We want to put our own
|
||||||
|
|
||||||
lexer.removeErrorListeners();
|
lexer.removeErrorListeners();
|
||||||
lexer.addErrorListener({
|
lexer.addErrorListener({
|
||||||
syntaxError(source, o, line, charPositionInLine, msg, error) {
|
syntaxError(source, o, line, charPositionInLine, msg, error) {
|
@@ -1,117 +0,0 @@
|
|||||||
import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor';
|
|
||||||
import { LoopStmtContext, ProgramContext } from '../../client/src/generated/bfParser';
|
|
||||||
import { bfVisitor } from '../../client/src/generated/bfVisitor';
|
|
||||||
import {getTree} from './bfGrammar';
|
|
||||||
import { DiagnosticSeverity } from 'vscode-languageserver-types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run BF code
|
|
||||||
* @param text
|
|
||||||
* @param fn
|
|
||||||
* @param input
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export async function runBF(text:string,fn:string,input:string){
|
|
||||||
//get tree and issues
|
|
||||||
const {tree,issues} = getTree(text,fn);
|
|
||||||
|
|
||||||
//get only errors
|
|
||||||
const x = issues.filter(e=>e.type===DiagnosticSeverity.Error);
|
|
||||||
//if any error, drop
|
|
||||||
if(x.length>0) {
|
|
||||||
throw Error('Errors exist');
|
|
||||||
}
|
|
||||||
// make visitor
|
|
||||||
const vis = new BFExecutor(input);
|
|
||||||
|
|
||||||
//visit the tree
|
|
||||||
vis.visit(tree);
|
|
||||||
|
|
||||||
//get output
|
|
||||||
return vis.outputStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class BFExecutor
|
|
||||||
extends AbstractParseTreeVisitor<void>
|
|
||||||
implements bfVisitor<void> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param input Input string
|
|
||||||
* @param inputPtr Input pointer to start from
|
|
||||||
*/
|
|
||||||
constructor(protected input: string='', protected inputPtr: number = 0) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* The memory cells (Can work with negative cells this way)
|
|
||||||
*/
|
|
||||||
protected cells: Map<number, number> = new Map();
|
|
||||||
/**
|
|
||||||
* Pointer
|
|
||||||
*/
|
|
||||||
protected ptr: number = 0;
|
|
||||||
/** Output string */
|
|
||||||
protected outputStrArray:string[]=[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Output string (Available only after visiting)
|
|
||||||
*/
|
|
||||||
public get outputStr(){
|
|
||||||
return this.outputStrArray.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
defaultResult() {}
|
|
||||||
|
|
||||||
visitLoopStmt(ctx:LoopStmtContext){
|
|
||||||
while((this.cells.get(this.ptr)??0)!==0){
|
|
||||||
this.visitChildren(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitPtrLeft() {
|
|
||||||
|
|
||||||
--this.ptr;
|
|
||||||
}
|
|
||||||
visitPtrRight() {
|
|
||||||
++this.ptr;
|
|
||||||
}
|
|
||||||
visitPtrIncr() {
|
|
||||||
|
|
||||||
const val = this.cells.get(this.ptr);
|
|
||||||
if (val === undefined) {
|
|
||||||
this.cells.set(this.ptr, 1);
|
|
||||||
} else if(val===255){
|
|
||||||
this.cells.delete(this.ptr);
|
|
||||||
}else{
|
|
||||||
this.cells.set(this.ptr, val + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitPtrDecr() {
|
|
||||||
// console.log('down',this.ptr,this.cells);
|
|
||||||
|
|
||||||
const val = this.cells.get(this.ptr);
|
|
||||||
if (val === undefined || val === 0) {
|
|
||||||
this.cells.set(this.ptr, 255);
|
|
||||||
} else if(val===1){
|
|
||||||
this.cells.delete(this.ptr);
|
|
||||||
}else{
|
|
||||||
this.cells.set(this.ptr, val - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitOutputStmt() {
|
|
||||||
const val = this.cells.get(this.ptr)??0;
|
|
||||||
const str = String.fromCharCode(val);
|
|
||||||
// console.log('op',str);
|
|
||||||
this.outputStrArray.push(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitInputStmt(){
|
|
||||||
//get char
|
|
||||||
const char = this.input.charCodeAt(this.inputPtr)??0;
|
|
||||||
//increment the input pointer after this
|
|
||||||
this.inputPtr++;
|
|
||||||
this.cells.set(this.ptr,char);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { workspace, ExtensionContext,commands, window } from 'vscode';
|
import { workspace, ExtensionContext,commands, window } from 'vscode';
|
||||||
import {runBF} from './bfExecutor';
|
|
||||||
import {
|
import {
|
||||||
LanguageClient,
|
LanguageClient,
|
||||||
LanguageClientOptions,
|
LanguageClientOptions,
|
||||||
ServerOptions,
|
ServerOptions,
|
||||||
TransportKind
|
TransportKind
|
||||||
} from 'vscode-languageclient';
|
} from 'vscode-languageclient';
|
||||||
|
import BranFlakesExecutorVisitor from './BranFlakesExecutorVisitor';
|
||||||
|
|
||||||
|
|
||||||
let client: LanguageClient;
|
let client: LanguageClient;
|
||||||
@@ -47,7 +47,9 @@ export function activate(context: ExtensionContext) {
|
|||||||
const text= window.activeTextEditor.document.getText();
|
const text= window.activeTextEditor.document.getText();
|
||||||
const fn = window.activeTextEditor.document.fileName;
|
const fn = window.activeTextEditor.document.fileName;
|
||||||
const input = await window.showInputBox({prompt:'Enter input (If not enough, program will assume 0)'});
|
const input = await window.showInputBox({prompt:'Enter input (If not enough, program will assume 0)'});
|
||||||
const output = await runBF(text,fn,input);
|
|
||||||
|
const output = BranFlakesExecutorVisitor.run(text,fn,input);
|
||||||
|
|
||||||
await window.showInformationMessage(`Output: ${output}`);
|
await window.showInformationMessage(`Output: ${output}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,10 +18,10 @@ import {
|
|||||||
Position,
|
Position,
|
||||||
} from 'vscode-languageserver';
|
} from 'vscode-languageserver';
|
||||||
|
|
||||||
// import * as path from 'path';
|
|
||||||
|
|
||||||
import { TextDocument } from 'vscode-languageserver-textdocument';
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
||||||
// import { getTree } from './bfGrammar';
|
|
||||||
|
|
||||||
// Create a connection for the server. The connection uses Node's IPC as a transport.
|
// Create a connection for the server. The connection uses Node's IPC as a transport.
|
||||||
// Also include all preview / proposed LSP features.
|
// Also include all preview / proposed LSP features.
|
||||||
|
Reference in New Issue
Block a user