8 Commits
0.0.1 ... 0.0.3

Author SHA1 Message Date
bf8d0f99d2 Merge branch 'main' of github.com:chrisvrose/bf-server 2021-04-18 00:51:59 +05:30
518e8ecbed Config
+ Add ignores for generated files
+ Add webpack
2021-04-18 00:50:38 +05:30
61d30947ce [eslint] add ignores for generated files 2021-04-18 00:49:55 +05:30
bef076239e [readme] update 2021-04-17 23:09:07 +05:30
d7d48785aa [client] exeute command 2021-04-17 23:03:40 +05:30
ed83e649fb [add] icon 2021-04-10 10:19:30 +05:30
19a479562c [package.json] change publisher 2021-04-10 09:54:46 +05:30
bfd36c5344 [readme] update 2021-04-10 00:11:36 +05:30
25 changed files with 9514 additions and 170 deletions

View File

@@ -3,3 +3,7 @@ client/node_modules/**
client/out/**
server/node_modules/**
server/out/**
server/dist/**
client/dist/**
client/src/generated/**

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
test.bf
out
dist
node_modules
client/server
.vscode-test

View File

@@ -1,14 +1,23 @@
**/out
*.bf
client/**
server/**
node_modules
!client/dist
!server/dist
**/*.md
!README.md
*.vsix
.vscode/**
**/*.ts
**/*.map
.gitignore
**/.gitignore
**/.eslintrc.json
**/.eslintignore
**/tsconfig.json
**/tsconfig.base.json
contributing.md
# contributing.md
.travis.yml
client/node_modules/**
!client/node_modules/vscode-jsonrpc/**
!client/node_modules/vscode-languageclient/**
!client/node_modules/vscode-languageserver-protocol/**
!client/node_modules/vscode-languageserver-types/**
!client/node_modules/semver/**
# client/node_modules/**

View File

@@ -1,6 +1,6 @@
# BF extension
A simple language server for the ~~Brainfuck~~ ~~Branflakes~~ BF language.
A simple language server based VSCode Extension for the ~~Brainfuck~~ ~~Branflakes~~ BF language. You can also execute your code and see its output.
![BF](https://chrisvrose.github.io/static/projects/screenshots/bf-server.png)
## Functionality
@@ -8,30 +8,14 @@ A simple language server for the ~~Brainfuck~~ ~~Branflakes~~ BF language.
- [X] Syntax
- [X] Bracket matching
- [X] Autocomplete suggestions
- [ ] Extension icon
- [X] Extension icon
- [X] Execution
- [ ] Timeout
<!--
## Structure
### Execution
```
.
├── client // Language Client
│ ├── src
│ │ ├── test // End to End tests for Language Client / Server
│ │ └── extension.ts // Language Client entry point
├── package.json // The extension manifest.
└── server // Language Server
└── src
└── server.ts // Language Server entry point
```
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).
## Running the Sample
- Run `npm install` in this folder. This installs all necessary npm modules in both the client and server folder
- Open VS Code on this folder.
- Press Ctrl+Shift+B to compile the client and server.
- Switch to the Debug viewlet.
- Select `Launch Client` from the drop down.
- Run the launch config.
- If you want to debug the server as well use the launch configuration `Attach to Server`
-->
TODO: Implement a timeout.

BIN
assets/128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

49
client/bf.g4 Normal file
View File

@@ -0,0 +1,49 @@
grammar bf;
program
: statements EOF;
statements
: eligibleStmt*;
eligibleStmt
: stmt
| numberedStmt
;
numberedStmt
: stmt NUMBER
;
stmt
: basicStmt
| loopStmt
;
loopStmt
: LOOPSTART statements LOOPEND
;
basicStmt
: INC # ptrIncr
| DEC # ptrDecr
| LEFT # ptrLeft
| RIGHT # ptrRight
| INPUT # inputStmt
| OUTPUT # outputStmt
;
LOOPSTART: '[';
LOOPEND:']';
NUMBER: [0-9]+;
INPUT: ',';
OUTPUT: '.';
DEC: '-';
INC: '+';
LEFT: '<';
RIGHT: '>';
EVERYTHING_ELSE: . ->channel(HIDDEN);
WS: [ \r\n] -> skip;

2359
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,10 +13,19 @@
"vscode": "^1.43.0"
},
"dependencies": {
"antlr4ts": "^0.5.0-alpha.4",
"vscode-languageclient": "^6.1.3"
},
"devDependencies": {
"@types/vscode": "1.43.0",
"vscode-test": "^1.3.0"
"vscode-test": "^1.3.0",
"webpack": "^5.33.2",
"webpack-cli": "^4.6.0"
},
"scripts": {
"regen": "antlr4ts bf.g4 -no-listener -visitor -o src/generated/",
"webpack": "webpack --mode development",
"webpack-prod":"webpack --mode production",
"webpack-dev": "webpack --mode development --watch"
}
}

117
client/src/bfExecutor.ts Normal file
View File

@@ -0,0 +1,117 @@
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);
}
}

56
client/src/bfGrammar.ts Normal file
View File

@@ -0,0 +1,56 @@
import { CharStreams, CommonTokenStream, RecognitionException } from 'antlr4ts';
import { DiagnosticSeverity } from 'vscode-languageserver-types';
import { bfLexer } from './generated/bfLexer';
import { bfParser } from './generated/bfParser';
export interface TranslationError {
line: number;
charPositionInLine: number;
msg: string;
source?: any;
type: DiagnosticSeverity;
error?: RecognitionException;
}
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) {
issues.push({
line,
charPositionInLine,
msg,
type: DiagnosticSeverity.Error,
source,
error,
});
},
});
const tokenStreams = new CommonTokenStream(lexer);
const parser = new bfParser(tokenStreams);
// remove the error listener. We want to put our own
parser.removeErrorListeners();
parser.addErrorListener({
syntaxError(source, o, line, charPositionInLine, msg, error) {
issues.push({
line,
charPositionInLine,
msg,
type: DiagnosticSeverity.Error,
source,
error,
});
},
});
const tree = parser.program();
return { tree, issues, tokenStreams, charStreams };
}

View File

@@ -5,7 +5,7 @@
import * as path from 'path';
import { workspace, ExtensionContext,commands, window } from 'vscode';
import {runBF} from './bfExecutor';
import {
LanguageClient,
LanguageClientOptions,
@@ -19,7 +19,7 @@ let client: LanguageClient;
export function activate(context: ExtensionContext) {
// The server is implemented in node
let serverModule = context.asAbsolutePath(
path.join('server', 'out', 'server.js')
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
@@ -42,6 +42,16 @@ export function activate(context: ExtensionContext) {
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}`);
};
context.subscriptions.push(commands.registerCommand(command,commandHandler));
// Create the language client and start the client.
client = new LanguageClient(

View File

@@ -0,0 +1,40 @@
token literal names:
null
'['
']'
null
','
'.'
'-'
'+'
'<'
'>'
null
null
token symbolic names:
null
LOOPSTART
LOOPEND
NUMBER
INPUT
OUTPUT
DEC
INC
LEFT
RIGHT
EVERYTHING_ELSE
WS
rule names:
program
statements
eligibleStmt
numberedStmt
stmt
loopStmt
basicStmt
atn:
[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 13, 49, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 3, 2, 3, 2, 3, 2, 3, 3, 7, 3, 21, 10, 3, 12, 3, 14, 3, 24, 11, 3, 3, 4, 3, 4, 5, 4, 28, 10, 4, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 5, 6, 35, 10, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 47, 10, 8, 3, 8, 2, 2, 2, 9, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 2, 2, 2, 49, 2, 16, 3, 2, 2, 2, 4, 22, 3, 2, 2, 2, 6, 27, 3, 2, 2, 2, 8, 29, 3, 2, 2, 2, 10, 34, 3, 2, 2, 2, 12, 36, 3, 2, 2, 2, 14, 46, 3, 2, 2, 2, 16, 17, 5, 4, 3, 2, 17, 18, 7, 2, 2, 3, 18, 3, 3, 2, 2, 2, 19, 21, 5, 6, 4, 2, 20, 19, 3, 2, 2, 2, 21, 24, 3, 2, 2, 2, 22, 20, 3, 2, 2, 2, 22, 23, 3, 2, 2, 2, 23, 5, 3, 2, 2, 2, 24, 22, 3, 2, 2, 2, 25, 28, 5, 10, 6, 2, 26, 28, 5, 8, 5, 2, 27, 25, 3, 2, 2, 2, 27, 26, 3, 2, 2, 2, 28, 7, 3, 2, 2, 2, 29, 30, 5, 10, 6, 2, 30, 31, 7, 5, 2, 2, 31, 9, 3, 2, 2, 2, 32, 35, 5, 14, 8, 2, 33, 35, 5, 12, 7, 2, 34, 32, 3, 2, 2, 2, 34, 33, 3, 2, 2, 2, 35, 11, 3, 2, 2, 2, 36, 37, 7, 3, 2, 2, 37, 38, 5, 4, 3, 2, 38, 39, 7, 4, 2, 2, 39, 13, 3, 2, 2, 2, 40, 47, 7, 9, 2, 2, 41, 47, 7, 8, 2, 2, 42, 47, 7, 10, 2, 2, 43, 47, 7, 11, 2, 2, 44, 47, 7, 6, 2, 2, 45, 47, 7, 7, 2, 2, 46, 40, 3, 2, 2, 2, 46, 41, 3, 2, 2, 2, 46, 42, 3, 2, 2, 2, 46, 43, 3, 2, 2, 2, 46, 44, 3, 2, 2, 2, 46, 45, 3, 2, 2, 2, 47, 15, 3, 2, 2, 2, 6, 22, 27, 34, 46]

View File

@@ -0,0 +1,19 @@
LOOPSTART=1
LOOPEND=2
NUMBER=3
INPUT=4
OUTPUT=5
DEC=6
INC=7
LEFT=8
RIGHT=9
EVERYTHING_ELSE=10
WS=11
'['=1
']'=2
','=4
'.'=5
'-'=6
'+'=7
'<'=8
'>'=9

View File

@@ -0,0 +1,50 @@
token literal names:
null
'['
']'
null
','
'.'
'-'
'+'
'<'
'>'
null
null
token symbolic names:
null
LOOPSTART
LOOPEND
NUMBER
INPUT
OUTPUT
DEC
INC
LEFT
RIGHT
EVERYTHING_ELSE
WS
rule names:
LOOPSTART
LOOPEND
NUMBER
INPUT
OUTPUT
DEC
INC
LEFT
RIGHT
EVERYTHING_ELSE
WS
channel names:
DEFAULT_TOKEN_CHANNEL
HIDDEN
mode names:
DEFAULT_MODE
atn:
[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 13, 54, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 6, 4, 31, 10, 4, 13, 4, 14, 4, 32, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 2, 2, 2, 13, 3, 2, 3, 5, 2, 4, 7, 2, 5, 9, 2, 6, 11, 2, 7, 13, 2, 8, 15, 2, 9, 17, 2, 10, 19, 2, 11, 21, 2, 12, 23, 2, 13, 3, 2, 4, 3, 2, 50, 59, 5, 2, 12, 12, 15, 15, 34, 34, 2, 54, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 3, 25, 3, 2, 2, 2, 5, 27, 3, 2, 2, 2, 7, 30, 3, 2, 2, 2, 9, 34, 3, 2, 2, 2, 11, 36, 3, 2, 2, 2, 13, 38, 3, 2, 2, 2, 15, 40, 3, 2, 2, 2, 17, 42, 3, 2, 2, 2, 19, 44, 3, 2, 2, 2, 21, 46, 3, 2, 2, 2, 23, 50, 3, 2, 2, 2, 25, 26, 7, 93, 2, 2, 26, 4, 3, 2, 2, 2, 27, 28, 7, 95, 2, 2, 28, 6, 3, 2, 2, 2, 29, 31, 9, 2, 2, 2, 30, 29, 3, 2, 2, 2, 31, 32, 3, 2, 2, 2, 32, 30, 3, 2, 2, 2, 32, 33, 3, 2, 2, 2, 33, 8, 3, 2, 2, 2, 34, 35, 7, 46, 2, 2, 35, 10, 3, 2, 2, 2, 36, 37, 7, 48, 2, 2, 37, 12, 3, 2, 2, 2, 38, 39, 7, 47, 2, 2, 39, 14, 3, 2, 2, 2, 40, 41, 7, 45, 2, 2, 41, 16, 3, 2, 2, 2, 42, 43, 7, 62, 2, 2, 43, 18, 3, 2, 2, 2, 44, 45, 7, 64, 2, 2, 45, 20, 3, 2, 2, 2, 46, 47, 11, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 49, 8, 11, 2, 2, 49, 22, 3, 2, 2, 2, 50, 51, 9, 3, 2, 2, 51, 52, 3, 2, 2, 2, 52, 53, 8, 12, 3, 2, 53, 24, 3, 2, 2, 2, 4, 2, 32, 4, 2, 3, 2, 8, 2, 2]

View File

@@ -0,0 +1,19 @@
LOOPSTART=1
LOOPEND=2
NUMBER=3
INPUT=4
OUTPUT=5
DEC=6
INC=7
LEFT=8
RIGHT=9
EVERYTHING_ELSE=10
WS=11
'['=1
']'=2
','=4
'.'=5
'-'=6
'+'=7
'<'=8
'>'=9

View File

@@ -0,0 +1,119 @@
// Generated from bf.g4 by ANTLR 4.9.0-SNAPSHOT
import { ATN } from "antlr4ts/atn/ATN";
import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer";
import { CharStream } from "antlr4ts/CharStream";
import { Lexer } from "antlr4ts/Lexer";
import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator";
import { NotNull } from "antlr4ts/Decorators";
import { Override } from "antlr4ts/Decorators";
import { RuleContext } from "antlr4ts/RuleContext";
import { Vocabulary } from "antlr4ts/Vocabulary";
import { VocabularyImpl } from "antlr4ts/VocabularyImpl";
import * as Utils from "antlr4ts/misc/Utils";
export class bfLexer extends Lexer {
public static readonly LOOPSTART = 1;
public static readonly LOOPEND = 2;
public static readonly NUMBER = 3;
public static readonly INPUT = 4;
public static readonly OUTPUT = 5;
public static readonly DEC = 6;
public static readonly INC = 7;
public static readonly LEFT = 8;
public static readonly RIGHT = 9;
public static readonly EVERYTHING_ELSE = 10;
public static readonly WS = 11;
// tslint:disable:no-trailing-whitespace
public static readonly channelNames: string[] = [
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
];
// tslint:disable:no-trailing-whitespace
public static readonly modeNames: string[] = [
"DEFAULT_MODE",
];
public static readonly ruleNames: string[] = [
"LOOPSTART", "LOOPEND", "NUMBER", "INPUT", "OUTPUT", "DEC", "INC", "LEFT",
"RIGHT", "EVERYTHING_ELSE", "WS",
];
private static readonly _LITERAL_NAMES: Array<string | undefined> = [
undefined, "'['", "']'", undefined, "','", "'.'", "'-'", "'+'", "'<'",
"'>'",
];
private static readonly _SYMBOLIC_NAMES: Array<string | undefined> = [
undefined, "LOOPSTART", "LOOPEND", "NUMBER", "INPUT", "OUTPUT", "DEC",
"INC", "LEFT", "RIGHT", "EVERYTHING_ELSE", "WS",
];
public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(bfLexer._LITERAL_NAMES, bfLexer._SYMBOLIC_NAMES, []);
// @Override
// @NotNull
public get vocabulary(): Vocabulary {
return bfLexer.VOCABULARY;
}
// tslint:enable:no-trailing-whitespace
constructor(input: CharStream) {
super(input);
this._interp = new LexerATNSimulator(bfLexer._ATN, this);
}
// @Override
public get grammarFileName(): string { return "bf.g4"; }
// @Override
public get ruleNames(): string[] { return bfLexer.ruleNames; }
// @Override
public get serializedATN(): string { return bfLexer._serializedATN; }
// @Override
public get channelNames(): string[] { return bfLexer.channelNames; }
// @Override
public get modeNames(): string[] { return bfLexer.modeNames; }
public static readonly _serializedATN: string =
"\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02\r6\b\x01\x04" +
"\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04" +
"\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x03\x02\x03" +
"\x02\x03\x03\x03\x03\x03\x04\x06\x04\x1F\n\x04\r\x04\x0E\x04 \x03\x05" +
"\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03\t\x03\t\x03\n" +
"\x03\n\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\f\x03\f\x02\x02\x02\r\x03" +
"\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t" +
"\x11\x02\n\x13\x02\v\x15\x02\f\x17\x02\r\x03\x02\x04\x03\x022;\x05\x02" +
"\f\f\x0F\x0F\"\"\x026\x02\x03\x03\x02\x02\x02\x02\x05\x03\x02\x02\x02" +
"\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02\x02\v\x03\x02\x02\x02\x02" +
"\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02\x11\x03\x02\x02\x02\x02" +
"\x13\x03\x02\x02\x02\x02\x15\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x03" +
"\x19\x03\x02\x02\x02\x05\x1B\x03\x02\x02\x02\x07\x1E\x03\x02\x02\x02\t" +
"\"\x03\x02\x02\x02\v$\x03\x02\x02\x02\r&\x03\x02\x02\x02\x0F(\x03\x02" +
"\x02\x02\x11*\x03\x02\x02\x02\x13,\x03\x02\x02\x02\x15.\x03\x02\x02\x02" +
"\x172\x03\x02\x02\x02\x19\x1A\x07]\x02\x02\x1A\x04\x03\x02\x02\x02\x1B" +
"\x1C\x07_\x02\x02\x1C\x06\x03\x02\x02\x02\x1D\x1F\t\x02\x02\x02\x1E\x1D" +
"\x03\x02\x02\x02\x1F \x03\x02\x02\x02 \x1E\x03\x02\x02\x02 !\x03\x02\x02" +
"\x02!\b\x03\x02\x02\x02\"#\x07.\x02\x02#\n\x03\x02\x02\x02$%\x070\x02" +
"\x02%\f\x03\x02\x02\x02&\'\x07/\x02\x02\'\x0E\x03\x02\x02\x02()\x07-\x02" +
"\x02)\x10\x03\x02\x02\x02*+\x07>\x02\x02+\x12\x03\x02\x02\x02,-\x07@\x02" +
"\x02-\x14\x03\x02\x02\x02./\v\x02\x02\x02/0\x03\x02\x02\x0201\b\v\x02" +
"\x021\x16\x03\x02\x02\x0223\t\x03\x02\x0234\x03\x02\x02\x0245\b\f\x03" +
"\x025\x18\x03\x02\x02\x02\x04\x02 \x04\x02\x03\x02\b\x02\x02";
public static __ATN: ATN;
public static get _ATN(): ATN {
if (!bfLexer.__ATN) {
bfLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(bfLexer._serializedATN));
}
return bfLexer.__ATN;
}
}

View File

@@ -0,0 +1,638 @@
// Generated from bf.g4 by ANTLR 4.9.0-SNAPSHOT
import { ATN } from "antlr4ts/atn/ATN";
import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer";
import { FailedPredicateException } from "antlr4ts/FailedPredicateException";
import { NotNull } from "antlr4ts/Decorators";
import { NoViableAltException } from "antlr4ts/NoViableAltException";
import { Override } from "antlr4ts/Decorators";
import { Parser } from "antlr4ts/Parser";
import { ParserRuleContext } from "antlr4ts/ParserRuleContext";
import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator";
import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener";
import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor";
import { RecognitionException } from "antlr4ts/RecognitionException";
import { RuleContext } from "antlr4ts/RuleContext";
//import { RuleVersion } from "antlr4ts/RuleVersion";
import { TerminalNode } from "antlr4ts/tree/TerminalNode";
import { Token } from "antlr4ts/Token";
import { TokenStream } from "antlr4ts/TokenStream";
import { Vocabulary } from "antlr4ts/Vocabulary";
import { VocabularyImpl } from "antlr4ts/VocabularyImpl";
import * as Utils from "antlr4ts/misc/Utils";
import { bfVisitor } from "./bfVisitor";
export class bfParser extends Parser {
public static readonly LOOPSTART = 1;
public static readonly LOOPEND = 2;
public static readonly NUMBER = 3;
public static readonly INPUT = 4;
public static readonly OUTPUT = 5;
public static readonly DEC = 6;
public static readonly INC = 7;
public static readonly LEFT = 8;
public static readonly RIGHT = 9;
public static readonly EVERYTHING_ELSE = 10;
public static readonly WS = 11;
public static readonly RULE_program = 0;
public static readonly RULE_statements = 1;
public static readonly RULE_eligibleStmt = 2;
public static readonly RULE_numberedStmt = 3;
public static readonly RULE_stmt = 4;
public static readonly RULE_loopStmt = 5;
public static readonly RULE_basicStmt = 6;
// tslint:disable:no-trailing-whitespace
public static readonly ruleNames: string[] = [
"program", "statements", "eligibleStmt", "numberedStmt", "stmt", "loopStmt",
"basicStmt",
];
private static readonly _LITERAL_NAMES: Array<string | undefined> = [
undefined, "'['", "']'", undefined, "','", "'.'", "'-'", "'+'", "'<'",
"'>'",
];
private static readonly _SYMBOLIC_NAMES: Array<string | undefined> = [
undefined, "LOOPSTART", "LOOPEND", "NUMBER", "INPUT", "OUTPUT", "DEC",
"INC", "LEFT", "RIGHT", "EVERYTHING_ELSE", "WS",
];
public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(bfParser._LITERAL_NAMES, bfParser._SYMBOLIC_NAMES, []);
// @Override
// @NotNull
public get vocabulary(): Vocabulary {
return bfParser.VOCABULARY;
}
// tslint:enable:no-trailing-whitespace
// @Override
public get grammarFileName(): string { return "bf.g4"; }
// @Override
public get ruleNames(): string[] { return bfParser.ruleNames; }
// @Override
public get serializedATN(): string { return bfParser._serializedATN; }
protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException {
return new FailedPredicateException(this, predicate, message);
}
constructor(input: TokenStream) {
super(input);
this._interp = new ParserATNSimulator(bfParser._ATN, this);
}
// @RuleVersion(0)
public program(): ProgramContext {
let _localctx: ProgramContext = new ProgramContext(this._ctx, this.state);
this.enterRule(_localctx, 0, bfParser.RULE_program);
try {
this.enterOuterAlt(_localctx, 1);
{
this.state = 14;
this.statements();
this.state = 15;
this.match(bfParser.EOF);
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
// @RuleVersion(0)
public statements(): StatementsContext {
let _localctx: StatementsContext = new StatementsContext(this._ctx, this.state);
this.enterRule(_localctx, 2, bfParser.RULE_statements);
let _la: number;
try {
this.enterOuterAlt(_localctx, 1);
{
this.state = 20;
this._errHandler.sync(this);
_la = this._input.LA(1);
while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << bfParser.LOOPSTART) | (1 << bfParser.INPUT) | (1 << bfParser.OUTPUT) | (1 << bfParser.DEC) | (1 << bfParser.INC) | (1 << bfParser.LEFT) | (1 << bfParser.RIGHT))) !== 0)) {
{
{
this.state = 17;
this.eligibleStmt();
}
}
this.state = 22;
this._errHandler.sync(this);
_la = this._input.LA(1);
}
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
// @RuleVersion(0)
public eligibleStmt(): EligibleStmtContext {
let _localctx: EligibleStmtContext = new EligibleStmtContext(this._ctx, this.state);
this.enterRule(_localctx, 4, bfParser.RULE_eligibleStmt);
try {
this.state = 25;
this._errHandler.sync(this);
switch ( this.interpreter.adaptivePredict(this._input, 1, this._ctx) ) {
case 1:
this.enterOuterAlt(_localctx, 1);
{
this.state = 23;
this.stmt();
}
break;
case 2:
this.enterOuterAlt(_localctx, 2);
{
this.state = 24;
this.numberedStmt();
}
break;
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
// @RuleVersion(0)
public numberedStmt(): NumberedStmtContext {
let _localctx: NumberedStmtContext = new NumberedStmtContext(this._ctx, this.state);
this.enterRule(_localctx, 6, bfParser.RULE_numberedStmt);
try {
this.enterOuterAlt(_localctx, 1);
{
this.state = 27;
this.stmt();
this.state = 28;
this.match(bfParser.NUMBER);
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
// @RuleVersion(0)
public stmt(): StmtContext {
let _localctx: StmtContext = new StmtContext(this._ctx, this.state);
this.enterRule(_localctx, 8, bfParser.RULE_stmt);
try {
this.state = 32;
this._errHandler.sync(this);
switch (this._input.LA(1)) {
case bfParser.INPUT:
case bfParser.OUTPUT:
case bfParser.DEC:
case bfParser.INC:
case bfParser.LEFT:
case bfParser.RIGHT:
this.enterOuterAlt(_localctx, 1);
{
this.state = 30;
this.basicStmt();
}
break;
case bfParser.LOOPSTART:
this.enterOuterAlt(_localctx, 2);
{
this.state = 31;
this.loopStmt();
}
break;
default:
throw new NoViableAltException(this);
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
// @RuleVersion(0)
public loopStmt(): LoopStmtContext {
let _localctx: LoopStmtContext = new LoopStmtContext(this._ctx, this.state);
this.enterRule(_localctx, 10, bfParser.RULE_loopStmt);
try {
this.enterOuterAlt(_localctx, 1);
{
this.state = 34;
this.match(bfParser.LOOPSTART);
this.state = 35;
this.statements();
this.state = 36;
this.match(bfParser.LOOPEND);
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
// @RuleVersion(0)
public basicStmt(): BasicStmtContext {
let _localctx: BasicStmtContext = new BasicStmtContext(this._ctx, this.state);
this.enterRule(_localctx, 12, bfParser.RULE_basicStmt);
try {
this.state = 44;
this._errHandler.sync(this);
switch (this._input.LA(1)) {
case bfParser.INC:
_localctx = new PtrIncrContext(_localctx);
this.enterOuterAlt(_localctx, 1);
{
this.state = 38;
this.match(bfParser.INC);
}
break;
case bfParser.DEC:
_localctx = new PtrDecrContext(_localctx);
this.enterOuterAlt(_localctx, 2);
{
this.state = 39;
this.match(bfParser.DEC);
}
break;
case bfParser.LEFT:
_localctx = new PtrLeftContext(_localctx);
this.enterOuterAlt(_localctx, 3);
{
this.state = 40;
this.match(bfParser.LEFT);
}
break;
case bfParser.RIGHT:
_localctx = new PtrRightContext(_localctx);
this.enterOuterAlt(_localctx, 4);
{
this.state = 41;
this.match(bfParser.RIGHT);
}
break;
case bfParser.INPUT:
_localctx = new InputStmtContext(_localctx);
this.enterOuterAlt(_localctx, 5);
{
this.state = 42;
this.match(bfParser.INPUT);
}
break;
case bfParser.OUTPUT:
_localctx = new OutputStmtContext(_localctx);
this.enterOuterAlt(_localctx, 6);
{
this.state = 43;
this.match(bfParser.OUTPUT);
}
break;
default:
throw new NoViableAltException(this);
}
}
catch (re) {
if (re instanceof RecognitionException) {
_localctx.exception = re;
this._errHandler.reportError(this, re);
this._errHandler.recover(this, re);
} else {
throw re;
}
}
finally {
this.exitRule();
}
return _localctx;
}
public static readonly _serializedATN: string =
"\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x03\r1\x04\x02\t" +
"\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07\t" +
"\x07\x04\b\t\b\x03\x02\x03\x02\x03\x02\x03\x03\x07\x03\x15\n\x03\f\x03" +
"\x0E\x03\x18\v\x03\x03\x04\x03\x04\x05\x04\x1C\n\x04\x03\x05\x03\x05\x03" +
"\x05\x03\x06\x03\x06\x05\x06#\n\x06\x03\x07\x03\x07\x03\x07\x03\x07\x03" +
"\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b/\n\b\x03\b\x02\x02\x02\t\x02\x02" +
"\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x02\x02\x021\x02\x10\x03\x02" +
"\x02\x02\x04\x16\x03\x02\x02\x02\x06\x1B\x03\x02\x02\x02\b\x1D\x03\x02" +
"\x02\x02\n\"\x03\x02\x02\x02\f$\x03\x02\x02\x02\x0E.\x03\x02\x02\x02\x10" +
"\x11\x05\x04\x03\x02\x11\x12\x07\x02\x02\x03\x12\x03\x03\x02\x02\x02\x13" +
"\x15\x05\x06\x04\x02\x14\x13\x03\x02\x02\x02\x15\x18\x03\x02\x02\x02\x16" +
"\x14\x03\x02\x02\x02\x16\x17\x03\x02\x02\x02\x17\x05\x03\x02\x02\x02\x18" +
"\x16\x03\x02\x02\x02\x19\x1C\x05\n\x06\x02\x1A\x1C\x05\b\x05\x02\x1B\x19" +
"\x03\x02\x02\x02\x1B\x1A\x03\x02\x02\x02\x1C\x07\x03\x02\x02\x02\x1D\x1E" +
"\x05\n\x06\x02\x1E\x1F\x07\x05\x02\x02\x1F\t\x03\x02\x02\x02 #\x05\x0E" +
"\b\x02!#\x05\f\x07\x02\" \x03\x02\x02\x02\"!\x03\x02\x02\x02#\v\x03\x02" +
"\x02\x02$%\x07\x03\x02\x02%&\x05\x04\x03\x02&\'\x07\x04\x02\x02\'\r\x03" +
"\x02\x02\x02(/\x07\t\x02\x02)/\x07\b\x02\x02*/\x07\n\x02\x02+/\x07\v\x02" +
"\x02,/\x07\x06\x02\x02-/\x07\x07\x02\x02.(\x03\x02\x02\x02.)\x03\x02\x02" +
"\x02.*\x03\x02\x02\x02.+\x03\x02\x02\x02.,\x03\x02\x02\x02.-\x03\x02\x02" +
"\x02/\x0F\x03\x02\x02\x02\x06\x16\x1B\".";
public static __ATN: ATN;
public static get _ATN(): ATN {
if (!bfParser.__ATN) {
bfParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(bfParser._serializedATN));
}
return bfParser.__ATN;
}
}
export class ProgramContext extends ParserRuleContext {
public statements(): StatementsContext {
return this.getRuleContext(0, StatementsContext);
}
public EOF(): TerminalNode { return this.getToken(bfParser.EOF, 0); }
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_program; }
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitProgram) {
return visitor.visitProgram(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class StatementsContext extends ParserRuleContext {
public eligibleStmt(): EligibleStmtContext[];
public eligibleStmt(i: number): EligibleStmtContext;
public eligibleStmt(i?: number): EligibleStmtContext | EligibleStmtContext[] {
if (i === undefined) {
return this.getRuleContexts(EligibleStmtContext);
} else {
return this.getRuleContext(i, EligibleStmtContext);
}
}
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_statements; }
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitStatements) {
return visitor.visitStatements(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class EligibleStmtContext extends ParserRuleContext {
public stmt(): StmtContext | undefined {
return this.tryGetRuleContext(0, StmtContext);
}
public numberedStmt(): NumberedStmtContext | undefined {
return this.tryGetRuleContext(0, NumberedStmtContext);
}
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_eligibleStmt; }
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitEligibleStmt) {
return visitor.visitEligibleStmt(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class NumberedStmtContext extends ParserRuleContext {
public stmt(): StmtContext {
return this.getRuleContext(0, StmtContext);
}
public NUMBER(): TerminalNode { return this.getToken(bfParser.NUMBER, 0); }
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_numberedStmt; }
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitNumberedStmt) {
return visitor.visitNumberedStmt(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class StmtContext extends ParserRuleContext {
public basicStmt(): BasicStmtContext | undefined {
return this.tryGetRuleContext(0, BasicStmtContext);
}
public loopStmt(): LoopStmtContext | undefined {
return this.tryGetRuleContext(0, LoopStmtContext);
}
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_stmt; }
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitStmt) {
return visitor.visitStmt(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class LoopStmtContext extends ParserRuleContext {
public LOOPSTART(): TerminalNode { return this.getToken(bfParser.LOOPSTART, 0); }
public statements(): StatementsContext {
return this.getRuleContext(0, StatementsContext);
}
public LOOPEND(): TerminalNode { return this.getToken(bfParser.LOOPEND, 0); }
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_loopStmt; }
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitLoopStmt) {
return visitor.visitLoopStmt(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class BasicStmtContext extends ParserRuleContext {
constructor(parent: ParserRuleContext | undefined, invokingState: number) {
super(parent, invokingState);
}
// @Override
public get ruleIndex(): number { return bfParser.RULE_basicStmt; }
public copyFrom(ctx: BasicStmtContext): void {
super.copyFrom(ctx);
}
}
export class PtrIncrContext extends BasicStmtContext {
public INC(): TerminalNode { return this.getToken(bfParser.INC, 0); }
constructor(ctx: BasicStmtContext) {
super(ctx.parent, ctx.invokingState);
this.copyFrom(ctx);
}
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitPtrIncr) {
return visitor.visitPtrIncr(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class PtrDecrContext extends BasicStmtContext {
public DEC(): TerminalNode { return this.getToken(bfParser.DEC, 0); }
constructor(ctx: BasicStmtContext) {
super(ctx.parent, ctx.invokingState);
this.copyFrom(ctx);
}
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitPtrDecr) {
return visitor.visitPtrDecr(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class PtrLeftContext extends BasicStmtContext {
public LEFT(): TerminalNode { return this.getToken(bfParser.LEFT, 0); }
constructor(ctx: BasicStmtContext) {
super(ctx.parent, ctx.invokingState);
this.copyFrom(ctx);
}
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitPtrLeft) {
return visitor.visitPtrLeft(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class PtrRightContext extends BasicStmtContext {
public RIGHT(): TerminalNode { return this.getToken(bfParser.RIGHT, 0); }
constructor(ctx: BasicStmtContext) {
super(ctx.parent, ctx.invokingState);
this.copyFrom(ctx);
}
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitPtrRight) {
return visitor.visitPtrRight(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class InputStmtContext extends BasicStmtContext {
public INPUT(): TerminalNode { return this.getToken(bfParser.INPUT, 0); }
constructor(ctx: BasicStmtContext) {
super(ctx.parent, ctx.invokingState);
this.copyFrom(ctx);
}
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitInputStmt) {
return visitor.visitInputStmt(this);
} else {
return visitor.visitChildren(this);
}
}
}
export class OutputStmtContext extends BasicStmtContext {
public OUTPUT(): TerminalNode { return this.getToken(bfParser.OUTPUT, 0); }
constructor(ctx: BasicStmtContext) {
super(ctx.parent, ctx.invokingState);
this.copyFrom(ctx);
}
// @Override
public accept<Result>(visitor: bfVisitor<Result>): Result {
if (visitor.visitOutputStmt) {
return visitor.visitOutputStmt(this);
} else {
return visitor.visitChildren(this);
}
}
}

View File

@@ -0,0 +1,126 @@
// Generated from bf.g4 by ANTLR 4.9.0-SNAPSHOT
import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor";
import { PtrIncrContext } from "./bfParser";
import { PtrDecrContext } from "./bfParser";
import { PtrLeftContext } from "./bfParser";
import { PtrRightContext } from "./bfParser";
import { InputStmtContext } from "./bfParser";
import { OutputStmtContext } from "./bfParser";
import { ProgramContext } from "./bfParser";
import { StatementsContext } from "./bfParser";
import { EligibleStmtContext } from "./bfParser";
import { NumberedStmtContext } from "./bfParser";
import { StmtContext } from "./bfParser";
import { LoopStmtContext } from "./bfParser";
import { BasicStmtContext } from "./bfParser";
/**
* This interface defines a complete generic visitor for a parse tree produced
* by `bfParser`.
*
* @param <Result> The return type of the visit operation. Use `void` for
* operations with no return type.
*/
export interface bfVisitor<Result> extends ParseTreeVisitor<Result> {
/**
* Visit a parse tree produced by the `ptrIncr`
* labeled alternative in `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitPtrIncr?: (ctx: PtrIncrContext) => Result;
/**
* Visit a parse tree produced by the `ptrDecr`
* labeled alternative in `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitPtrDecr?: (ctx: PtrDecrContext) => Result;
/**
* Visit a parse tree produced by the `ptrLeft`
* labeled alternative in `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitPtrLeft?: (ctx: PtrLeftContext) => Result;
/**
* Visit a parse tree produced by the `ptrRight`
* labeled alternative in `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitPtrRight?: (ctx: PtrRightContext) => Result;
/**
* Visit a parse tree produced by the `inputStmt`
* labeled alternative in `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitInputStmt?: (ctx: InputStmtContext) => Result;
/**
* Visit a parse tree produced by the `outputStmt`
* labeled alternative in `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitOutputStmt?: (ctx: OutputStmtContext) => Result;
/**
* Visit a parse tree produced by `bfParser.program`.
* @param ctx the parse tree
* @return the visitor result
*/
visitProgram?: (ctx: ProgramContext) => Result;
/**
* Visit a parse tree produced by `bfParser.statements`.
* @param ctx the parse tree
* @return the visitor result
*/
visitStatements?: (ctx: StatementsContext) => Result;
/**
* Visit a parse tree produced by `bfParser.eligibleStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitEligibleStmt?: (ctx: EligibleStmtContext) => Result;
/**
* Visit a parse tree produced by `bfParser.numberedStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitNumberedStmt?: (ctx: NumberedStmtContext) => Result;
/**
* Visit a parse tree produced by `bfParser.stmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitStmt?: (ctx: StmtContext) => Result;
/**
* Visit a parse tree produced by `bfParser.loopStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitLoopStmt?: (ctx: LoopStmtContext) => Result;
/**
* Visit a parse tree produced by `bfParser.basicStmt`.
* @param ctx the parse tree
* @return the visitor result
*/
visitBasicStmt?: (ctx: BasicStmtContext) => Result;
}

51
client/webpack.config.js Normal file
View File

@@ -0,0 +1,51 @@
//@ts-check
'use strict';
const path = require('path');
// const {} = require('webpack');
/**@type {import('webpack').Configuration}*/
const config = {
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
entry: {
extension:path.join(__dirname,'src','extension.ts'),
}, // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'
},
devtool: 'source-map',
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js'],
plugins:[]
},
stats:'minimal',
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options:{
configFile : 'tsconfig.json'
}
}
],
}
]
},
};
module.exports = config;

3478
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,19 @@
{
"name": "bfc-server",
"displayName": "BF Language",
"description": "Brainfuck",
"author": "Rose",
"description": "BF Syntax Support",
"author": "Atreya Bain",
"license": "MIT",
"publisher": "Rose",
"version": "0.0.1",
"publisher": "atreyabain",
"version": "0.0.3",
"icon": "assets/128.png",
"categories": [],
"keywords": [
"multi-root ready",
"brainfuck",
"branflakes"
],
"prettier":{
"prettier": {
"tabWidth": 4,
"semi": true,
"arrowParens": "avoid",
@@ -26,9 +27,9 @@
],
"repository": {
"type": "git",
"url":"https://github.com/chrisvrose/bf-server"
"url": "https://github.com/chrisvrose/bf-server"
},
"main": "./client/out/extension",
"main": "./client/dist/extension",
"contributes": {
"languages": [
{
@@ -54,7 +55,14 @@
"path": "./syntaxes/bf.tmLanguage.json"
}
],
"commands": [],
"commands": [
{
"command": "bf.execute",
"title": "BF: Execute",
"when": "editorLangId == bf",
"enablement": "editorLangId == bf"
}
],
"configuration": {
"type": "object",
"title": "Configurable properties",
@@ -81,7 +89,8 @@
},
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -b",
"compile": "concurrently \"npm run webpack-prod --prefix client\" \"npm run webpack-prod --prefix server \"",
"_compile": "tsc -b",
"watch": "tsc -b -w",
"postinstall": "cd client && npm install && cd ../server && npm install && cd .."
},
@@ -92,6 +101,12 @@
"@typescript-eslint/parser": "^2.33.0",
"eslint": "^6.4.0",
"mocha": "^6.2.2",
"typescript": "^3.9.2"
"ts-loader": "^8.1.0",
"typescript": "^3.9.2",
"webpack": "^5.33.2",
"webpack-cli": "^4.6.0"
},
"dependencies": {
"concurrently": "^6.0.2"
}
}

2348
server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,5 +15,13 @@
"vscode-languageserver": "^6.1.1",
"vscode-languageserver-textdocument": "^1.0.1"
},
"scripts": {}
"scripts": {
"webpack-prod":"webpack --mode production",
"webpack": "webpack --mode development",
"webpack-dev": "webpack --mode development --watch"
},
"devDependencies": {
"webpack": "^5.33.2",
"webpack-cli": "^4.6.0"
}
}

View File

@@ -21,6 +21,7 @@ import {
// 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.
@@ -149,19 +150,19 @@ documents.onDidSave(change => {
const validateBrackets = (text: string) => {
let count = 0, lp: number[] = [],issues:number[]=[];
const textsplit = text.split(``);
const textsplit = text.split('');
textsplit.forEach((x, i) => {
if (x == '[' || x == ']') {
if (x === '[' || x === ']') {
if (x == '[') lp.push(i);
if (x == ']') {if(lp.length==0) issues.push(i);lp.pop();}
if (x === '[') {lp.push(i);}
if (x === ']') {if(lp.length===0) {issues.push(i);}lp.pop();}
}
});
return [...lp,...issues]
return [...lp,...issues];
};
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
@@ -174,15 +175,15 @@ async function validateTextDocument(textDocument: TextDocument): Promise<void> {
let diagnostics: Diagnostic[] = [];
const issues = validateBrackets(text);
diagnostics.push(...issues.map<Diagnostic>(e => ({
message: 'Brackets unmatched',
range:{
start: textDocument.positionAt(e),
end: textDocument.positionAt(e+1),
},
severity:DiagnosticSeverity.Error,
code:'[ and ]',
})));
diagnostics.push(...issues.map<Diagnostic>(e => ({
message: 'Brackets unmatched',
range:{
start: textDocument.positionAt(e),
end: textDocument.positionAt(e+1),
},
severity:DiagnosticSeverity.Error,
code:'[ and ]',
})));
// diagnostics.push({
// message: 'Brackets not matched',

50
server/webpack.config.js Normal file
View File

@@ -0,0 +1,50 @@
//@ts-check
'use strict';
const path = require('path');
/**@type {import('webpack').Configuration}*/
const config = {
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
entry: {
server:path.join(__dirname,'src','server.ts'),
}, // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../[resource-path]'
},
stats:'minimal',
devtool: 'source-map',
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js'],
plugins:[]
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options:{
configFile : 'tsconfig.json'
}
}
],
}
]
},
};
module.exports = config;