This commit is contained in:
2023-12-15 14:27:11 +05:30
parent f8083b26d2
commit 36ed3328d1
5 changed files with 123 additions and 122 deletions

View 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);
}
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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}`);
}; };

View File

@@ -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.