[client] exeute command

This commit is contained in:
2021-04-17 23:03:40 +05:30
parent ed83e649fb
commit d7d48785aa
16 changed files with 1298 additions and 16 deletions

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