mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-16 14:25:03 +01:00
interpreter
This commit is contained in:
parent
b30fa04dcc
commit
e815fd8c66
8 changed files with 647 additions and 19 deletions
|
|
@ -1,3 +1,7 @@
|
|||
$main-color: #282c34;
|
||||
$main-color-brighter: #323942;
|
||||
$font-color: ghostwhite;
|
||||
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -8,16 +12,48 @@
|
|||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
background-color: $main-color;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
color: $font-color;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
.bf-input {
|
||||
.code-input {
|
||||
resize: none;
|
||||
width: 80vw;
|
||||
height: 400px;
|
||||
font-size: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.bf-run {
|
||||
margin: 20px;
|
||||
|
||||
button {
|
||||
height: 50px;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.bf-output {
|
||||
.output-area {
|
||||
resize: none;
|
||||
width: 80vw;
|
||||
height: 200px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: $main-color-brighter;
|
||||
color: $font-color;
|
||||
}
|
||||
|
|
@ -1,13 +1,35 @@
|
|||
import './App.scss';
|
||||
import CodeInput from "./components/CodeInput";
|
||||
import ProgramOutput from "./components/ProgramOutput";
|
||||
import React, {useState} from "react";
|
||||
import Interpreter from "./brainfuck/Interpreter";
|
||||
import RunInfo from "./components/RunInfo";
|
||||
|
||||
function App() {
|
||||
const [interpreter, setInterpreter] = useState<Interpreter | null>(null);
|
||||
|
||||
const [out, setOut] = useState("");
|
||||
const [input, setInput] = useState("");
|
||||
|
||||
const outHandler = (char: number) => {
|
||||
setOut(out => out + String.fromCharCode(char))
|
||||
}
|
||||
|
||||
const inHandler = (): number => {
|
||||
return 65;
|
||||
}
|
||||
|
||||
const start = () => setInterpreter(new Interpreter(input, outHandler, inHandler));
|
||||
const next = () => interpreter?.next();
|
||||
const prev = () => interpreter?.prev();
|
||||
|
||||
return (
|
||||
<div className="App-header">
|
||||
<div className="bf-input">
|
||||
<textarea placeholder="Input your code here..."/>
|
||||
</div>
|
||||
<CodeInput setInput={input => setInput(input)}/>
|
||||
<RunInfo nextHandler={next} prevHandler={prev} startHandler={start} interpreter={interpreter}/>
|
||||
<ProgramOutput text={out}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
76
ibfi-ts/src/brainfuck/Interpreter.ts
Normal file
76
ibfi-ts/src/brainfuck/Interpreter.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
export default class Interpreter {
|
||||
private readonly _array: Uint8Array;
|
||||
private _pointer: number;
|
||||
private readonly _code: string;
|
||||
private _codePointer: number;
|
||||
|
||||
private _inHandler: (() => number);
|
||||
private _outHandler: ((char: number) => void);
|
||||
|
||||
constructor(code: string, outHandler: ((char: number) => void), inHandler: (() => number)) {
|
||||
const buf = new ArrayBuffer(32000);
|
||||
this._array = new Uint8Array(buf);
|
||||
this._pointer = 0;
|
||||
this._code = code;
|
||||
this._codePointer = 0;
|
||||
this._inHandler = inHandler;
|
||||
this._outHandler = outHandler;
|
||||
}
|
||||
|
||||
public next() {
|
||||
switch (this._code[++this._codePointer]) {
|
||||
case '+':
|
||||
this._array[this._pointer]++;
|
||||
break;
|
||||
case '-':
|
||||
this._array[this._pointer]--;
|
||||
break;
|
||||
case '>':
|
||||
this._pointer++;
|
||||
break;
|
||||
case '<':
|
||||
this._pointer--;
|
||||
break;
|
||||
case '.':
|
||||
this._outHandler(this._array[this._pointer]);
|
||||
break;
|
||||
case ',':
|
||||
this._array[this._pointer] = this._inHandler();
|
||||
break;
|
||||
case '[':
|
||||
console.error("does not support [ for now")
|
||||
break;
|
||||
case ']':
|
||||
console.error("does not support ] for now")
|
||||
break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
console.log("next step")
|
||||
}
|
||||
|
||||
public prev() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
get value(): number {
|
||||
return this._array[this._pointer];
|
||||
}
|
||||
|
||||
get array(): Uint8Array {
|
||||
return this._array;
|
||||
}
|
||||
|
||||
get pointer(): number {
|
||||
return this._pointer;
|
||||
}
|
||||
|
||||
get code(): string {
|
||||
return this._code;
|
||||
}
|
||||
|
||||
get codePointer(): number {
|
||||
return this._codePointer;
|
||||
}
|
||||
}
|
||||
23
ibfi-ts/src/components/CodeInput.tsx
Normal file
23
ibfi-ts/src/components/CodeInput.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import React, {useState} from 'react';
|
||||
|
||||
interface CodeInputProps {
|
||||
setInput: ((input: string) => void),
|
||||
}
|
||||
|
||||
const CodeInput = ({setInput}: CodeInputProps) => {
|
||||
const [fontSize, setFontSize] = useState(40);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="bf-input">
|
||||
<div>
|
||||
<label htmlFor="bf-input-fontsize-range">Font Size</label>
|
||||
<input type="range" id="bf-input-fontsize-range" onChange={v => setFontSize(+v.target.value)}/>
|
||||
</div>
|
||||
<textarea onChange={e => setInput(e.target.value)} style={{fontSize}} className="code-input" placeholder="Input your code here..."/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeInput;
|
||||
15
ibfi-ts/src/components/ProgramOutput.tsx
Normal file
15
ibfi-ts/src/components/ProgramOutput.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react';
|
||||
|
||||
interface ProgramOutputProps {
|
||||
text: string
|
||||
}
|
||||
|
||||
const ProgramOutput = ({text}: ProgramOutputProps) => {
|
||||
return (
|
||||
<div className="bf-output">
|
||||
<textarea readOnly className="output-area" value={text}/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProgramOutput;
|
||||
28
ibfi-ts/src/components/RunInfo.tsx
Normal file
28
ibfi-ts/src/components/RunInfo.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import React from 'react';
|
||||
import Interpreter from "../brainfuck/Interpreter";
|
||||
|
||||
interface RunInfoProps {
|
||||
nextHandler: () => void,
|
||||
prevHandler: () => void,
|
||||
startHandler: () => void,
|
||||
interpreter: Interpreter | null,
|
||||
}
|
||||
|
||||
const RunInfo = ({interpreter, ...props}: RunInfoProps) => {
|
||||
return (
|
||||
<div className="bf-run">
|
||||
<div>
|
||||
<button onClick={props.startHandler}>Start</button>
|
||||
<button onClick={props.nextHandler}>Next</button>
|
||||
<button onClick={props.prevHandler}>Previous</button>
|
||||
</div>
|
||||
|
||||
{interpreter &&
|
||||
<div>Pointer: {interpreter.pointer} value {interpreter.value}</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
;
|
||||
|
||||
export default RunInfo;
|
||||
Loading…
Add table
Add a link
Reference in a new issue