Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
0a2a6c4db6 | |||
6e143cd4d0 | |||
f094584dee | |||
c01c04699a | |||
e6fea932d8 | |||
e90524e367 | |||
c117337883 | |||
da08fb3979 | |||
a15429d964 | |||
36ed3328d1 | |||
f8083b26d2 |
201
LICENSE
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2022 Atreya Bain
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
38
README.md
38
README.md
@@ -1,21 +1,39 @@
|
||||
# BF extension
|
||||
|
||||
A simple language server based VSCode Extension for the ~~Brainfuck~~ ~~Branflakes~~ BF language. You can also execute your code and see its output.
|
||||
A simple language server based VSCode Extension for the (Branflakes?) (BrainFuck?) BF language. You can also execute your code and see its output.
|
||||
|
||||

|
||||
|
||||

|
||||
## Functionality
|
||||
|
||||
- [X] Syntax
|
||||
- [X] Bracket matching
|
||||
- [X] Autocomplete suggestions
|
||||
- [X] Extension icon
|
||||
- [X] Execution
|
||||
- [ ] Timeout
|
||||
- Syntax Highlighting
|
||||
- Execution
|
||||
- Autocomplete suggestions
|
||||
|
||||
|
||||
### Execution
|
||||
|
||||
Use the command to execute the code.
|
||||
Issue is, because BF is a *turing complete* language, there is no way to know if the program will terminate or not. Hence for now, the command may lead to infinite execution.
|
||||
Additionally, all input is done before program execution (If the program requests for input that hasn't been provided, `zero` is fed to it).
|
||||
Issue is, because BF is a **turing complete** language, there is no way to know if the program will terminate or not. Hence for now, the command may lead to infinite execution.
|
||||
If the program requires input, it will be requested as a prompt.
|
||||
|
||||
TODO: Implement a timeout.
|
||||
|
||||
### Changelog
|
||||
|
||||
#### 0.2.0
|
||||
|
||||
- Cycle input pointer on overflow/underflow
|
||||
- Refactoring code
|
||||
|
||||
#### 0.1.0
|
||||
|
||||
- Request input as required during execution
|
||||
- Using array-based indexing. This implies that only positive indices upto 30k are supported.
|
||||
|
||||
|
||||
### Building it
|
||||
|
||||
1. `npm i` - Install all dependencies
|
||||
2. `npm i -g @vscode/vsce` - Install VSCode Command line CLI
|
||||
3. `vsce package` - Package to VSIX
|
BIN
assets/screenshot.png
Normal file
BIN
assets/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
140
client/src/BranFlakesExecutorVisitor.ts
Normal file
140
client/src/BranFlakesExecutorVisitor.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
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';
|
||||
import { RuleNode } from 'antlr4ts/tree/RuleNode';
|
||||
import InputStrategy from './input/InputStrategy';
|
||||
|
||||
export default class BranFlakesExecutorVisitor
|
||||
extends AbstractParseTreeVisitor<Promise<void>>
|
||||
implements bfVisitor<Promise<void>>
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param input Input string
|
||||
* @param inputPtr Input pointer to start from
|
||||
*/
|
||||
constructor(
|
||||
private inputStrategy: InputStrategy,
|
||||
private logger: (val: string) => Thenable<string>,
|
||||
private inputPtr: number = 0
|
||||
) {
|
||||
super();
|
||||
}
|
||||
// /**
|
||||
// * The memory cells (Can work with negative cells this way)
|
||||
// */
|
||||
// private cells: Map<number, number> = new Map();
|
||||
|
||||
private byteArraySize: number = 30000;
|
||||
private byteArray: Int8Array = new Int8Array(this.byteArraySize);
|
||||
/**
|
||||
* Pointer
|
||||
*/
|
||||
private ptr: number = 0;
|
||||
/** Output string */
|
||||
private outputStr: string = '';
|
||||
|
||||
|
||||
|
||||
defaultResult() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
/**
|
||||
* Run a file
|
||||
* @param text
|
||||
* @param fn
|
||||
* @param inputStrategy
|
||||
* @returns
|
||||
*/
|
||||
static async run(
|
||||
text: string,
|
||||
fn: string,
|
||||
inputStrategy: InputStrategy,
|
||||
logger: (str: string) => Thenable<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(inputStrategy, logger);
|
||||
//visit the tree
|
||||
await vis.visit(tree);
|
||||
|
||||
//get output
|
||||
return vis.outputStr;
|
||||
}
|
||||
|
||||
getCell(pointerIndex: number) {
|
||||
return this.byteArray[pointerIndex];
|
||||
}
|
||||
setCell(pointerIndex: number, value: number): void {
|
||||
this.byteArray[pointerIndex] = value;
|
||||
}
|
||||
|
||||
async visitLoopStmt(ctx: LoopStmtContext) {
|
||||
while ((this.getCell(this.ptr) ?? 0) !== 0) {
|
||||
await this.visitChildren(ctx);
|
||||
}
|
||||
}
|
||||
async visitPtrLeft() {
|
||||
this.ptr = (this.ptr + this.byteArraySize - 1) % this.byteArraySize;
|
||||
}
|
||||
async visitPtrRight() {
|
||||
this.ptr = (this.ptr + this.byteArraySize + 1) % this.byteArraySize;
|
||||
}
|
||||
async visitPtrIncr() {
|
||||
const val = this.getCell(this.ptr);
|
||||
this.setCell(this.ptr, (val + 1) % 256);
|
||||
}
|
||||
async visitPtrDecr() {
|
||||
const val = this.getCell(this.ptr);
|
||||
this.setCell(this.ptr, (val + 255) % 256);
|
||||
}
|
||||
async visitOutputStmt() {
|
||||
const val = this.getCell(this.ptr) ?? 0;
|
||||
const str = String.fromCharCode(val);
|
||||
|
||||
this.outputStr += str;
|
||||
}
|
||||
|
||||
async visitInputStmt() {
|
||||
//get char
|
||||
const char = (await this.inputStrategy.getInput()) ?? 0;
|
||||
//increment the input pointer after this
|
||||
this.inputPtr++;
|
||||
this.setCell(this.ptr, char);
|
||||
}
|
||||
|
||||
// override for maintaining async
|
||||
async visitChildren(node: RuleNode): Promise<void> {
|
||||
let result = this.defaultResult();
|
||||
await result;
|
||||
let n = node.childCount;
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (!this.shouldVisitNextChild(node, result)) {
|
||||
break;
|
||||
}
|
||||
let c = node.getChild(i);
|
||||
let childResult = c.accept(this);
|
||||
result = this.aggregateResult(result, childResult);
|
||||
await result;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
// override for maintaining async
|
||||
protected async aggregateResult(
|
||||
aggregate: Promise<void>,
|
||||
nextResult: Promise<void>
|
||||
): Promise<void> {
|
||||
await aggregate;
|
||||
return nextResult;
|
||||
}
|
||||
}
|
@@ -16,9 +16,9 @@ export interface TranslationError {
|
||||
export function getTree(str: string, fn: string) {
|
||||
const charStreams = CharStreams.fromString(str, fn);
|
||||
const lexer = new bfLexer(charStreams);
|
||||
// const errorListener = this.errorManager.newErrorListener();
|
||||
const issues: TranslationError[] = [];
|
||||
// remove the error listener. We want to put our own
|
||||
|
||||
lexer.removeErrorListeners();
|
||||
lexer.addErrorListener({
|
||||
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
client/src/command/Command.ts
Normal file
5
client/src/command/Command.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
export interface Command{
|
||||
getCommandName():string;
|
||||
getCommandHandler():(...args:any)=>Promise<any>;
|
||||
}
|
26
client/src/command/CompileCommand.ts
Normal file
26
client/src/command/CompileCommand.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { window } from 'vscode';
|
||||
import { Command as BranFlakesCommand } from './Command';
|
||||
import { VSCodePromptInputStrategy } from '../input/VSCodePromptInputStrategy';
|
||||
import BranFlakesExecutorVisitor from '../BranFlakesExecutorVisitor';
|
||||
|
||||
export class CompileBranFlakesCommand implements BranFlakesCommand {
|
||||
getCommandName() {
|
||||
return 'bf.execute';
|
||||
}
|
||||
getCommandHandler() {
|
||||
return async () => {
|
||||
const text = window.activeTextEditor.document.getText();
|
||||
const fn = window.activeTextEditor.document.fileName;
|
||||
const inputStrategy = new VSCodePromptInputStrategy(
|
||||
window.showInputBox
|
||||
);
|
||||
const output = await BranFlakesExecutorVisitor.run(
|
||||
text,
|
||||
fn,
|
||||
inputStrategy,
|
||||
window.showInformationMessage
|
||||
);
|
||||
await window.showInformationMessage(`Output: ${output}`);
|
||||
};
|
||||
}
|
||||
}
|
@@ -4,70 +4,68 @@
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
|
||||
import * as path from 'path';
|
||||
import { workspace, ExtensionContext,commands, window } from 'vscode';
|
||||
import {runBF} from './bfExecutor';
|
||||
import { ExtensionContext, commands, window } from 'vscode';
|
||||
import {
|
||||
LanguageClient,
|
||||
LanguageClientOptions,
|
||||
ServerOptions,
|
||||
TransportKind
|
||||
LanguageClient,
|
||||
LanguageClientOptions,
|
||||
ServerOptions,
|
||||
TransportKind,
|
||||
} from 'vscode-languageclient';
|
||||
|
||||
import { CompileBranFlakesCommand } from './command/CompileCommand';
|
||||
|
||||
let client: LanguageClient;
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
// The server is implemented in node
|
||||
let serverModule = context.asAbsolutePath(
|
||||
path.join('server', 'dist', 'server.js')
|
||||
);
|
||||
// The debug options for the server
|
||||
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
|
||||
let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
|
||||
// The server is implemented in node
|
||||
let serverModule = context.asAbsolutePath(
|
||||
path.join('server', 'dist', 'server.js')
|
||||
);
|
||||
// The debug options for the server
|
||||
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
|
||||
let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
|
||||
|
||||
// If the extension is launched in debug mode then the debug server options are used
|
||||
// Otherwise the run options are used
|
||||
let serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
options: debugOptions
|
||||
}
|
||||
};
|
||||
// If the extension is launched in debug mode then the debug server options are used
|
||||
// Otherwise the run options are used
|
||||
let serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
options: debugOptions,
|
||||
},
|
||||
};
|
||||
|
||||
// Options to control the language client
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
// Register the server for plain text documents
|
||||
documentSelector: [{ scheme: 'file', language: 'bf' }]
|
||||
};
|
||||
// Options to control the language client
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
// Register the server for plain text documents
|
||||
documentSelector: [{ scheme: 'file', language: 'bf' }],
|
||||
};
|
||||
|
||||
const command = 'bf.execute';
|
||||
const commandHandler = async()=>{
|
||||
const text= window.activeTextEditor.document.getText();
|
||||
const fn = window.activeTextEditor.document.fileName;
|
||||
const input = await window.showInputBox({prompt:'Enter input (If not enough, program will assume 0)'});
|
||||
const output = await runBF(text,fn,input);
|
||||
await window.showInformationMessage(`Output: ${output}`);
|
||||
};
|
||||
const branFlakesCommands = [new CompileBranFlakesCommand()];
|
||||
for (let branFlakesCommand of branFlakesCommands) {
|
||||
context.subscriptions.push(
|
||||
commands.registerCommand(
|
||||
branFlakesCommand.getCommandName(),
|
||||
branFlakesCommand.getCommandHandler()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
context.subscriptions.push(commands.registerCommand(command,commandHandler));
|
||||
// Create the language client and start the client.
|
||||
client = new LanguageClient(
|
||||
'brainfucklanguageserver',
|
||||
'Brainfuck Language Server',
|
||||
serverOptions,
|
||||
clientOptions
|
||||
);
|
||||
|
||||
// Create the language client and start the client.
|
||||
client = new LanguageClient(
|
||||
'brainfucklanguageserver',
|
||||
'Brainfuck Language Server',
|
||||
serverOptions,
|
||||
clientOptions
|
||||
);
|
||||
|
||||
// Start the client. This will also launch the server
|
||||
client.start();
|
||||
// Start the client. This will also launch the server
|
||||
client.start();
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> | undefined {
|
||||
if (!client) {
|
||||
return undefined;
|
||||
}
|
||||
return client.stop();
|
||||
if (!client) {
|
||||
return undefined;
|
||||
}
|
||||
return client.stop();
|
||||
}
|
||||
|
4
client/src/input/InputStrategy.ts
Normal file
4
client/src/input/InputStrategy.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
export default interface InputStrategy {
|
||||
getInput(): Promise<number>;
|
||||
}
|
28
client/src/input/VSCodePromptInputStrategy.ts
Normal file
28
client/src/input/VSCodePromptInputStrategy.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { CancellationToken, InputBoxOptions } from 'vscode';
|
||||
import InputStrategy from './InputStrategy';
|
||||
|
||||
export class VSCodePromptInputStrategy implements InputStrategy {
|
||||
private inputQueue: string = '';
|
||||
constructor(
|
||||
private requestor: (
|
||||
promptOptions?: InputBoxOptions,
|
||||
cancelToken?: CancellationToken
|
||||
) => Thenable<string>
|
||||
) {}
|
||||
|
||||
async getInput(): Promise<number> {
|
||||
while (this.inputQueue.length == 0) {
|
||||
await this.requestInputFromPrompt();
|
||||
}
|
||||
const character = this.inputQueue.charCodeAt(0);
|
||||
this.inputQueue = this.inputQueue.substring(1);
|
||||
|
||||
return character;
|
||||
}
|
||||
private async requestInputFromPrompt() {
|
||||
const inputPrompt = await this.requestor({
|
||||
prompt: 'More input is required. Please provide input:',
|
||||
});
|
||||
this.inputQueue += inputPrompt;
|
||||
}
|
||||
}
|
1386
package-lock.json
generated
1386
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
"author": "Atreya Bain",
|
||||
"license": "MIT",
|
||||
"publisher": "atreyabain",
|
||||
"version": "0.0.4",
|
||||
"version": "0.2.0",
|
||||
"icon": "assets/128.png",
|
||||
"categories": [],
|
||||
"keywords": [
|
||||
|
@@ -18,10 +18,10 @@ import {
|
||||
Position,
|
||||
} from 'vscode-languageserver';
|
||||
|
||||
// import * as path from 'path';
|
||||
|
||||
|
||||
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.
|
||||
// Also include all preview / proposed LSP features.
|
||||
|
Reference in New Issue
Block a user