├── src ├── main │ ├── resources │ │ ├── include-me.bf │ │ ├── include-base.bf │ │ ├── algorithms │ │ │ └── x_equals_y.algo │ │ ├── net │ │ │ └── zomis │ │ │ │ └── brainf │ │ │ │ └── ui │ │ │ │ ├── styles.css │ │ │ │ ├── tabcontent.fxml │ │ │ │ └── brainf.fxml │ │ ├── fizzbuzz-min.bf │ │ └── fizzbuzz.bf │ └── groovy │ │ └── net │ │ └── zomis │ │ └── brainf │ │ ├── model │ │ ├── groovy │ │ │ ├── WrapBehavior.groovy │ │ │ ├── ArrayBuilder.groovy │ │ │ ├── GroovyBFContext.groovy │ │ │ ├── GroovyListener.java │ │ │ ├── GroovySupportConverter.groovy │ │ │ └── SpecialDelegate.groovy │ │ ├── BrainfuckOutput.groovy │ │ ├── BrainfuckInput.groovy │ │ ├── ast │ │ │ ├── transform │ │ │ │ ├── CopyMoveSyntax.java │ │ │ │ ├── Translator.java │ │ │ │ └── OutSyntax.java │ │ │ ├── tree │ │ │ │ ├── LoopInstructionSyntax.java │ │ │ │ ├── SteppableSyntax.java │ │ │ │ ├── PrintSyntax.java │ │ │ │ ├── Syntax.java │ │ │ │ ├── ReadSyntax.java │ │ │ │ ├── CommentSyntax.java │ │ │ │ ├── ChangeValueSyntax.java │ │ │ │ ├── SyntaxTree.java │ │ │ │ ├── ChangePointerSyntax.java │ │ │ │ ├── GroovySyntax.java │ │ │ │ └── Parser.java │ │ │ ├── CommentToken.java │ │ │ ├── Token.java │ │ │ ├── GroovyToken.java │ │ │ ├── BFToken.java │ │ │ ├── TokenInfo.java │ │ │ └── Lexer.java │ │ ├── BrainfuckCommand.java │ │ ├── BrainfuckCodeConverter.groovy │ │ ├── run │ │ │ ├── RunStrategy.groovy │ │ │ ├── UntilEndStrategy.groovy │ │ │ ├── StepOutStrategy.groovy │ │ │ ├── RunUntilLoopStartStrategy.groovy │ │ │ ├── LimitedStepsStrategy.groovy │ │ │ └── StepContinueStrategy.groovy │ │ ├── input │ │ │ ├── ConsoleOutput.java │ │ │ ├── NoInput.java │ │ │ ├── FixedInput.groovy │ │ │ ├── ConsoleInput.java │ │ │ ├── StringBuilderOutput.groovy │ │ │ └── QueueInput.java │ │ ├── CodeRetriever.java │ │ ├── BrainfuckException.java │ │ ├── BrainfuckListener.java │ │ ├── classic │ │ │ ├── BrainfuckConverter.groovy │ │ │ ├── BFLoop.java │ │ │ └── BrainFCommand.java │ │ ├── SubCommand.groovy │ │ ├── BrainF.java │ │ ├── SyntaxTreePosition.groovy │ │ ├── ListCode.groovy │ │ ├── BrainfuckCode.groovy │ │ ├── BrainfuckMemory.groovy │ │ └── BrainfuckRunner.groovy │ │ ├── analyze │ │ ├── CellTagger.groovy │ │ ├── InspectionResult.groovy │ │ ├── analyzers │ │ │ ├── BrainfuckAnalyzers.groovy │ │ │ ├── IOAnalysis.groovy │ │ │ ├── MemoryValues.groovy │ │ │ ├── GroovyCommandAnalysis.groovy │ │ │ ├── MemoryIndexAnalysis.groovy │ │ │ ├── ReadWriteAnalysis.groovy │ │ │ ├── WhileLoopAnalysis.groovy │ │ │ ├── CodeCellRelationAnalysis.groovy │ │ │ ├── CommandCountAnalysis.groovy │ │ │ └── PlusMinusOptimizer.groovy │ │ ├── BrainfuckAnalyzer.java │ │ ├── IndexCounters.groovy │ │ ├── Brainalyze.groovy │ │ ├── AnalyzeFactory.groovy │ │ ├── MemoryCell.groovy │ │ └── IndexCounter.groovy │ │ ├── ui │ │ ├── CommandLineOptions.java │ │ ├── GroovyRead.groovy │ │ ├── TextAppender.groovy │ │ ├── BFTaskAnalyze.java │ │ ├── Brainduck.java │ │ ├── BrainduckFX.java │ │ ├── LoadSaveHandler.groovy │ │ ├── BFTask.java │ │ └── EditorStyle.groovy │ │ ├── BrainfuckCompilationException.groovy │ │ ├── tools │ │ ├── WeightedPerformanceScorer.groovy │ │ └── textgen │ │ │ ├── TextCellGroup.groovy │ │ │ ├── TextGenFactorization.groovy │ │ │ └── TextGenerator.groovy │ │ └── dsl │ │ ├── ExternalAlgorithm.groovy │ │ └── BrainDSL.groovy └── test │ ├── groovy │ └── net │ │ └── zomis │ │ └── brainf │ │ ├── ValidateTest.groovy │ │ ├── ast │ │ └── transform │ │ │ └── TranslatorTest2.groovy │ │ ├── ScriptTest.groovy │ │ ├── OptimizeTest.java │ │ ├── RunStrategyTest.groovy │ │ ├── BrainUnitTest.groovy │ │ ├── ParserTest.groovy │ │ ├── BrainfuckTest.groovy │ │ └── LexerTest.groovy │ └── resources │ └── net │ └── zomis │ └── brainf │ └── ast │ └── transform │ └── helloWorldNoLoop.bf ├── settings.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── Jenkinsfile ├── README.md ├── .gitignore ├── gradlew.bat └── gradlew /src/main/resources/include-me.bf: -------------------------------------------------------------------------------- 1 | [>+<-]> 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Brainduck' 2 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | #Tue, 01 Nov 2016 14:23:08 +0100 2 | version=0.0.6-SNAPSHOT 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zomis/Brainduck/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/groovy/WrapBehavior.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.groovy 2 | 3 | enum WrapBehavior { 4 | ALLOW, BLOCK, CRASH 5 | } 6 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainfuckOutput.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model 2 | 3 | interface BrainfuckOutput { 4 | 5 | void write(char value) 6 | 7 | } -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainfuckInput.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model 2 | 3 | interface BrainfuckInput { 4 | 5 | int read() throws BrainfuckException 6 | 7 | } -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/transform/CopyMoveSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.transform; 2 | 3 | public class CopyMoveSyntax { 4 | 5 | int[] changes; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainfuckCommand.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model; 2 | 3 | @Deprecated 4 | public interface BrainfuckCommand { 5 | 6 | void perform(BrainfuckRunner runner); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/include-base.bf: -------------------------------------------------------------------------------- 1 | > +++++ ++ > +++++ 2 | < 3 | 4 | $ include 'include-me' // this file will gather all the values at one place 5 | 6 | $ assert value == 12 7 | < 8 | $ assert value == 0 9 | >> 10 | $ assert value == 0 11 | -------------------------------------------------------------------------------- /src/main/resources/algorithms/x_equals_y.algo: -------------------------------------------------------------------------------- 1 | // https://esolangs.org/wiki/Brainfuck_algorithms#x_.3D_y 2 | 3 | temp 'temp0' 4 | variables 'x', 'y' 5 | 6 | code ''' 7 | temp0[-] 8 | x[-] 9 | y[x+temp0+y-] 10 | temp0[y+temp0-] 11 | ''' 12 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainfuckCodeConverter.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model 2 | 3 | import java.util.function.Consumer 4 | 5 | interface BrainfuckCodeConverter { 6 | 7 | void convert(String code, Consumer add) 8 | 9 | } 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Dec 02 20:15:45 GMT+01:00 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-all.zip 7 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/run/RunStrategy.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.run 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner 4 | 5 | interface RunStrategy { 6 | 7 | boolean start(BrainfuckRunner runner) 8 | boolean next(BrainfuckRunner runner) 9 | 10 | } -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/analyze/CellTagger.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.analyze 2 | 3 | import java.util.function.Function 4 | import java.util.stream.Stream 5 | 6 | interface CellTagger { 7 | 8 | Stream tags(Function indexToStringFunction) 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/input/ConsoleOutput.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.input; 2 | 3 | import net.zomis.brainf.model.BrainfuckOutput; 4 | 5 | public class ConsoleOutput implements BrainfuckOutput { 6 | @Override 7 | public void write(char value) { 8 | System.out.print(value); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/CodeRetriever.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model; 2 | 3 | @Deprecated 4 | public interface CodeRetriever { 5 | 6 | BrainfuckCommand getCommand(int commandIndex); 7 | 8 | default int getCommandLength(int commandIndex) { 9 | return 1; 10 | } 11 | 12 | int capacity(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/LoopInstructionSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | 5 | public class LoopInstructionSyntax extends SyntaxTree { 6 | 7 | @Override 8 | public void perform(BrainfuckRunner runner) { 9 | 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/ui/CommandLineOptions.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.ui; 2 | 3 | import com.beust.jcommander.Parameter; 4 | 5 | import java.util.List; 6 | 7 | public class CommandLineOptions { 8 | 9 | @Parameter 10 | List main; 11 | 12 | @Parameter(names = "-analyze") 13 | boolean analyze = false; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/BrainfuckCompilationException.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf 2 | 3 | class BrainfuckCompilationException extends RuntimeException { 4 | 5 | BrainfuckCompilationException(String var1) { 6 | super(var1) 7 | } 8 | 9 | BrainfuckCompilationException(String var1, Throwable var2) { 10 | super(var1, var2) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/SteppableSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | 5 | public interface SteppableSyntax { 6 | 7 | int getValue(); 8 | void performTimes(BrainfuckRunner runner, int steps); 9 | default int getTimes() { 10 | return Math.abs(getValue()); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/PrintSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | 5 | public class PrintSyntax extends Syntax { 6 | 7 | @Override 8 | public void perform(BrainfuckRunner runner) { 9 | char write = (char) runner.getMemory().getValue(); 10 | runner.appendOutput(write); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/ui/GroovyRead.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.ui 2 | 3 | /** 4 | * Utility class for Java code to make it easier to read from resources or files 5 | */ 6 | class GroovyRead { 7 | static String read(String s) { 8 | return GroovyRead.getClassLoader().getResource(s).text; 9 | } 10 | static String file(File file) { 11 | return file.text; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/input/NoInput.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.input; 2 | 3 | import net.zomis.brainf.model.BrainfuckException; 4 | import net.zomis.brainf.model.BrainfuckInput; 5 | 6 | public class NoInput implements BrainfuckInput { 7 | 8 | @Override 9 | public int read() throws BrainfuckException { 10 | throw new BrainfuckException("Not implemented"); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | @Library('ZomisJenkins') 4 | import net.zomis.jenkins.Duga 5 | 6 | node { 7 | stage('Checkout') { 8 | checkout scm 9 | } 10 | stage('Build') { 11 | sh './gradlew dist' 12 | } 13 | stage('Reports') { 14 | junit 'build/test-results/*.xml' 15 | new Duga().dugaResult('SUCCESS') 16 | } 17 | stage('Archive') { 18 | archiveArtifacts artifacts: 'build/libs/*-all.jar' 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainfuckException.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model; 2 | 3 | public class BrainfuckException extends Exception { 4 | 5 | public BrainfuckException() { 6 | } 7 | 8 | public BrainfuckException(String message) { 9 | super(message); 10 | } 11 | 12 | public BrainfuckException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public BrainfuckException(Throwable cause) { 17 | super(cause); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/CommentToken.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast; 2 | 3 | public class CommentToken extends Token { 4 | 5 | public final String text; 6 | 7 | public CommentToken(TokenInfo tokenInfo, String text) { 8 | super(tokenInfo); 9 | this.text = text; 10 | } 11 | 12 | @Override 13 | public String toString() { 14 | return "CommentToken{" + 15 | "text='" + text + '\'' + 16 | "} " + super.toString(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/Token.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast; 2 | 3 | public class Token { 4 | 5 | private TokenInfo info; 6 | 7 | public Token(TokenInfo tokenInfo) { 8 | this.info = new TokenInfo(tokenInfo); 9 | } 10 | 11 | public TokenInfo getInfo() { 12 | return new TokenInfo(info); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "Token{" + 18 | "info=" + info + 19 | '}'; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/Syntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | import net.zomis.brainf.model.ast.Token; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public abstract class Syntax { 10 | 11 | private final List tokens = new ArrayList<>(); 12 | 13 | public List getTokens() { 14 | return tokens; 15 | } 16 | 17 | public abstract void perform(BrainfuckRunner runner); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/GroovyToken.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast; 2 | 3 | public class GroovyToken extends Token { 4 | 5 | public final String code; 6 | 7 | public GroovyToken(TokenInfo tokenInfo, String groovyCode) { 8 | super(tokenInfo); 9 | this.code = groovyCode; 10 | } 11 | 12 | @Override 13 | public String toString() { 14 | return "GroovyToken{" + 15 | "code='" + code + '\'' + 16 | "} " + super.toString(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/input/FixedInput.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.input 2 | 3 | import net.zomis.brainf.model.BrainfuckException 4 | import net.zomis.brainf.model.BrainfuckInput 5 | 6 | class FixedInput implements BrainfuckInput { 7 | 8 | final String text 9 | private int pos 10 | 11 | public FixedInput(String input) { 12 | this.text = input; 13 | } 14 | 15 | @Override 16 | public int read() throws BrainfuckException { 17 | return text.charAt(pos++); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/ui/TextAppender.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.ui 2 | 3 | import javafx.application.Platform 4 | import javafx.scene.control.TextArea 5 | import net.zomis.brainf.model.BrainfuckOutput 6 | 7 | class TextAppender implements BrainfuckOutput { 8 | private final TextArea textArea 9 | 10 | TextAppender(TextArea textArea) { 11 | this.textArea = textArea 12 | } 13 | 14 | @Override 15 | void write(char value) { 16 | Platform.runLater({ textArea.appendText(String.valueOf(value)) }) 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/input/ConsoleInput.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.input; 2 | 3 | import net.zomis.brainf.model.BrainfuckException; 4 | import net.zomis.brainf.model.BrainfuckInput; 5 | 6 | import java.io.IOException; 7 | 8 | public class ConsoleInput implements BrainfuckInput { 9 | 10 | @Override 11 | public int read() throws BrainfuckException { 12 | try { 13 | return System.in.read(); 14 | } catch (IOException e) { 15 | throw new BrainfuckException(e); 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/tools/WeightedPerformanceScorer.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.tools 2 | 3 | class WeightedPerformanceScorer { 4 | 5 | private final double codeWeight 6 | private final double runtimeWeight 7 | 8 | WeightedPerformanceScorer(double codeWeight, double runtimeWeight) { 9 | this.codeWeight = codeWeight 10 | this.runtimeWeight = runtimeWeight 11 | } 12 | 13 | int score(int codeLength, int runtimeLength) { 14 | return (int) (codeWeight * codeLength + runtimeWeight * runtimeLength) 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/input/StringBuilderOutput.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.input 2 | 3 | import net.zomis.brainf.model.BrainfuckOutput 4 | 5 | class StringBuilderOutput implements BrainfuckOutput { 6 | 7 | private final StringBuilder output 8 | 9 | StringBuilderOutput(StringBuilder output) { 10 | this.output = output 11 | } 12 | 13 | @Override 14 | void write(char value) { 15 | output.append(value) 16 | } 17 | 18 | @Override 19 | String toString() { 20 | output.toString() 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainfuckListener.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model; 2 | 3 | import net.zomis.brainf.model.ast.tree.Syntax; 4 | 5 | public interface BrainfuckListener { 6 | default void beforePerform(BrainfuckRunner runner, Syntax command) {} 7 | default void afterPerform(BrainfuckRunner runner, Syntax command) {} 8 | 9 | default void beforeWhile(BrainfuckRunner runner) {} 10 | default void afterWhile(BrainfuckRunner runner) {} 11 | default void beforeEndWhile(BrainfuckRunner runner) {} 12 | default void afterEndWhile(BrainfuckRunner runner) {} 13 | } 14 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/ReadSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckException; 4 | import net.zomis.brainf.model.BrainfuckRunner; 5 | 6 | public class ReadSyntax extends Syntax { 7 | 8 | @Override 9 | public void perform(BrainfuckRunner runner) { 10 | int value; 11 | try { 12 | value = runner.getInput().read(); 13 | } catch (BrainfuckException e) { 14 | throw new RuntimeException(e); 15 | } 16 | runner.getMemory().setMemory(value); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/classic/BrainfuckConverter.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.classic 2 | 3 | import net.zomis.brainf.model.BrainfuckCodeConverter 4 | import net.zomis.brainf.model.BrainfuckCommand 5 | 6 | import java.util.function.Consumer 7 | 8 | class BrainfuckConverter implements BrainfuckCodeConverter { 9 | 10 | @Override 11 | void convert(String str, Consumer add) { 12 | str.chars().mapToObj({i -> BrainFCommand.getCommand((char) i)}) 13 | .filter({obj -> obj != null}) 14 | .forEachOrdered(add); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/transform/Translator.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.transform; 2 | 3 | import net.zomis.brainf.model.ast.tree.SyntaxTree; 4 | 5 | /** 6 | * For finding patterns in BF code to make it more understandable 7 | */ 8 | public class Translator { 9 | 10 | public SyntaxTree translate(SyntaxTree root) { 11 | // check for loops 12 | // count the number of nested loops. If it is many then the outer ones must be some looping 13 | // check for memory setup 14 | // check for what is printed 15 | 16 | 17 | return null; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/run/UntilEndStrategy.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.run 2 | 3 | import groovy.transform.CompileStatic 4 | import net.zomis.brainf.model.BrainfuckRunner 5 | 6 | @CompileStatic 7 | class UntilEndStrategy implements RunStrategy { 8 | 9 | @Override 10 | boolean start(BrainfuckRunner runner) { 11 | return true 12 | } 13 | 14 | @Override 15 | boolean next(BrainfuckRunner runner) { 16 | if (runner.code.isFinished()) { 17 | return false; 18 | } 19 | runner.runSyntax() 20 | return !runner.code.isFinished() 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/CommentSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | import net.zomis.brainf.model.ast.CommentToken; 5 | 6 | public class CommentSyntax extends Syntax { 7 | 8 | private final CommentToken token; 9 | 10 | public CommentSyntax(CommentToken token) { 11 | this.token = token; 12 | } 13 | 14 | @Override 15 | public void perform(BrainfuckRunner runner) { 16 | 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return "CommentSyntax{" + token.text + '}'; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/BFToken.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast; 2 | 3 | import net.zomis.brainf.model.BrainfuckCommand; 4 | import net.zomis.brainf.model.classic.BrainFCommand; 5 | 6 | public class BFToken extends Token { 7 | 8 | public final BrainfuckCommand command; 9 | 10 | public BFToken(TokenInfo tokenInfo, BrainFCommand bfCommand) { 11 | super(tokenInfo); 12 | this.command = bfCommand; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "BFToken{" + 18 | "command=" + command + 19 | "} " + super.toString(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/transform/OutSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.transform; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | import net.zomis.brainf.model.ast.tree.Syntax; 5 | 6 | public class OutSyntax extends Syntax { 7 | 8 | private final String text; 9 | 10 | public OutSyntax(String text) { 11 | this.text = text; 12 | } 13 | 14 | public String getText() { 15 | return text; 16 | } 17 | 18 | @Override 19 | public void perform(BrainfuckRunner runner) { 20 | for (int i = 0; i < text.length(); i++) { 21 | runner.appendOutput(text.charAt(i)); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/analyze/InspectionResult.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.analyze 2 | 3 | class InspectionResult { 4 | 5 | public enum InspectionSeverity { 6 | HINT, WARNING, ERROR; 7 | } 8 | 9 | final InspectionSeverity severity 10 | 11 | final int commandIndexStart 12 | final int commandIndexEnd 13 | 14 | final String description 15 | 16 | InspectionResult(InspectionSeverity severity, int start, int end, String description) { 17 | this.severity = severity 18 | this.commandIndexStart = start 19 | this.commandIndexEnd = end 20 | this.description = description 21 | } 22 | 23 | @Override 24 | String toString() { 25 | return "[$commandIndexStart--$commandIndexEnd] $severity: $description" 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/SubCommand.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model 2 | 3 | import groovy.transform.CompileStatic 4 | import net.zomis.brainf.model.ast.tree.Syntax 5 | import net.zomis.brainf.model.ast.tree.SyntaxTree 6 | import net.zomis.brainf.model.run.UntilEndStrategy 7 | 8 | @CompileStatic 9 | class SubCommand extends Syntax { 10 | 11 | private final SyntaxTree tree; 12 | 13 | SubCommand(SyntaxTree tree) { 14 | this.tree = tree 15 | } 16 | 17 | @Override 18 | void perform(BrainfuckRunner runner) { 19 | BrainfuckRunner subRunner = new BrainfuckRunner(runner.memory, new BrainfuckCode(), 20 | runner.input, runner.outputBuilder) 21 | subRunner.code.rootTree = tree 22 | subRunner.run(new UntilEndStrategy()) 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/net/zomis/brainf/ui/styles.css: -------------------------------------------------------------------------------- 1 | .code { 2 | -fx-fill: purple; 3 | -fx-font-weight: bold; 4 | } 5 | .loop { 6 | -fx-fill: darkgreen; 7 | -fx-font-weight: bold; 8 | } 9 | .comment { 10 | -fx-fill: cadetblue; 11 | } 12 | .io { 13 | -fx-fill: blue; 14 | } 15 | 16 | .highlighted { 17 | -fx-background-fill: yellow; 18 | } 19 | 20 | .keyword { 21 | -fx-fill: purple; 22 | -fx-font-weight: bold; 23 | } 24 | .semicolon { 25 | -fx-font-weight: bold; 26 | } 27 | .paren { 28 | -fx-fill: firebrick; 29 | -fx-font-weight: bold; 30 | } 31 | .bracket { 32 | -fx-fill: darkgreen; 33 | -fx-font-weight: bold; 34 | } 35 | .brace { 36 | -fx-fill: teal; 37 | -fx-font-weight: bold; 38 | } 39 | .string { 40 | -fx-fill: blue; 41 | } 42 | 43 | #output { 44 | -fx-font-family: monospace; 45 | } -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/analyze/analyzers/BrainfuckAnalyzers.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.analyze.analyzers 2 | 3 | import net.zomis.brainf.analyze.BrainfuckAnalyzer 4 | 5 | class BrainfuckAnalyzers { 6 | 7 | public static BrainfuckAnalyzer[] getAvailableAnalyzers() { 8 | // TODO Change BF Analyzers to use AST 9 | BrainfuckAnalyzer[] analyzers = [ 10 | new GroovyCommandAnalysis(), // Static analysis 11 | new IOAnalysis(), 12 | new MemoryValues(), 13 | new ReadWriteAnalysis(), 14 | new WhileLoopAnalysis(), 15 | new CommandCountAnalysis(), // Code commands is static analysis 16 | new MemoryIndexAnalysis(), 17 | new PlusMinusOptimizer(), // Static analysis 18 | new CodeCellRelationAnalysis(), 19 | ] 20 | analyzers 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/classic/BFLoop.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.classic; 2 | 3 | import net.zomis.brainf.model.BrainfuckCommand; 4 | import net.zomis.brainf.model.BrainfuckRunner; 5 | 6 | @Deprecated 7 | public class BFLoop implements BrainfuckCommand { 8 | 9 | private final int i; 10 | 11 | public BFLoop(int i) { 12 | this.i = i; 13 | } 14 | 15 | 16 | @Override 17 | public void perform(BrainfuckRunner runner) { 18 | if (i == 1) { 19 | if (runner.getMemory().getValue() == 0) { 20 | throw new UnsupportedOperationException(); 21 | } 22 | } else if (i == -1) { 23 | if (runner.getMemory().getValue() != 0) { 24 | throw new UnsupportedOperationException(); 25 | } 26 | } else { 27 | throw new IllegalStateException("Invalid i: " + i); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/BrainF.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model; 2 | 3 | import net.zomis.brainf.model.ast.Lexer; 4 | import net.zomis.brainf.model.ast.tree.Parser; 5 | import net.zomis.brainf.model.groovy.GroovyBFContext; 6 | import net.zomis.brainf.model.input.QueueInput; 7 | 8 | import java.util.concurrent.BlockingQueue; 9 | 10 | public class BrainF { 11 | public static BrainfuckRunner createUsingQueueWithMemorySize(BlockingQueue input, 12 | int memorySize, BrainfuckOutput output) { 13 | return new BrainfuckRunner(new BrainfuckMemory(memorySize), new BrainfuckCode(), new QueueInput(input), output); 14 | } 15 | 16 | public static BrainfuckCode code(String code) { 17 | BrainfuckCode bfCode = new BrainfuckCode(); 18 | bfCode.setRootTree(new Parser(new GroovyBFContext()).parse(Lexer.tokenize(code))); 19 | bfCode.setSource(ListCode.create(code)); 20 | return bfCode; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/input/QueueInput.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.input; 2 | 3 | import net.zomis.brainf.model.BrainfuckException; 4 | import net.zomis.brainf.model.BrainfuckInput; 5 | 6 | import java.util.Objects; 7 | import java.util.concurrent.BlockingQueue; 8 | 9 | public class QueueInput implements BrainfuckInput { 10 | private final BlockingQueue queue; 11 | 12 | public QueueInput(BlockingQueue input) { 13 | Objects.requireNonNull(input, "Queue input may not be null"); 14 | this.queue = input; 15 | } 16 | 17 | public BlockingQueue getQueue() { 18 | return queue; 19 | } 20 | 21 | @Override 22 | public int read() throws BrainfuckException { 23 | try { 24 | return queue.take(); 25 | } catch (InterruptedException e) { 26 | throw new BrainfuckException("Interrupted while retrieving input", e); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/run/StepOutStrategy.groovy: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.run 2 | 3 | import net.zomis.brainf.model.ast.tree.SyntaxTree 4 | import net.zomis.brainf.model.BrainfuckRunner 5 | 6 | class StepOutStrategy implements RunStrategy { 7 | 8 | private int enteredSyntaxes 9 | private SyntaxTree activeTree 10 | 11 | @Override 12 | boolean start(BrainfuckRunner runner) { 13 | enteredSyntaxes = runner.code.enteredTrees.size() 14 | activeTree = runner.code.currentTree.tree 15 | if (runner.code.currentSyntax instanceof SyntaxTree) { 16 | return false 17 | } 18 | return enteredSyntaxes > 1 19 | } 20 | 21 | @Override 22 | boolean next(BrainfuckRunner runner) { 23 | runner.runSyntax() 24 | if (runner.code.currentSyntax == activeTree) { 25 | return true 26 | } 27 | return runner.code.enteredTrees.size() >= enteredSyntaxes 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/ChangeValueSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | 5 | public class ChangeValueSyntax extends Syntax implements SteppableSyntax { 6 | 7 | private final int value; 8 | 9 | public ChangeValueSyntax(int value) { 10 | this.value = value; 11 | } 12 | 13 | @Override 14 | public int getValue() { 15 | return value; 16 | } 17 | 18 | @Override 19 | public void perform(BrainfuckRunner runner) { 20 | performTimes(runner, Math.abs(value)); 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "ChangeValueSyntax{" + 26 | "value=" + value + 27 | '}'; 28 | } 29 | 30 | @Override 31 | public void performTimes(BrainfuckRunner runner, int steps) { 32 | steps = value >= 0 ? steps : -steps; 33 | runner.getMemory().changeMemory(steps); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/SyntaxTree.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.ListIterator; 8 | 9 | public class SyntaxTree extends Syntax implements Iterable { 10 | 11 | public List syntax = new ArrayList<>(); 12 | 13 | @Override 14 | public void perform(BrainfuckRunner runner) { 15 | throw new IllegalStateException("Cannot perform a full syntax tree at once"); 16 | } 17 | 18 | @Override 19 | public ListIterator iterator() { 20 | return syntax.listIterator(); 21 | } 22 | 23 | public ListIterator iteratorAt(int index) { 24 | return syntax.listIterator(index); 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "SyntaxTree{" + 30 | "syntax=" + syntax + 31 | '}'; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/model/ast/tree/ChangePointerSyntax.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.model.ast.tree; 2 | 3 | import net.zomis.brainf.model.BrainfuckRunner; 4 | 5 | public class ChangePointerSyntax extends Syntax implements SteppableSyntax { 6 | 7 | private final int value; 8 | 9 | public ChangePointerSyntax(int value) { 10 | this.value = value; 11 | } 12 | 13 | @Override 14 | public int getValue() { 15 | return value; 16 | } 17 | 18 | @Override 19 | public void perform(BrainfuckRunner runner) { 20 | performTimes(runner, Math.abs(value)); 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "ChangePointerSyntax{" + 26 | "value=" + value + 27 | '}'; 28 | } 29 | 30 | @Override 31 | public void performTimes(BrainfuckRunner runner, int steps) { 32 | steps = value >= 0 ? steps : -steps; 33 | runner.getMemory().setMemoryIndex(runner.getMemory().getMemoryIndex() + steps); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/groovy/net/zomis/brainf/analyze/BrainfuckAnalyzer.java: -------------------------------------------------------------------------------- 1 | package net.zomis.brainf.analyze; 2 | 3 | import groovy.transform.CompileStatic; 4 | import net.zomis.brainf.model.BrainfuckRunner; 5 | import net.zomis.brainf.model.ast.tree.Syntax; 6 | 7 | @CompileStatic 8 | public interface BrainfuckAnalyzer { 9 | 10 | default Object createMemoryData() { return null; } 11 | default void beforeStart(BrainfuckRunner runner) { } 12 | default void after(Brainalyze analyze, BrainfuckRunner runner) { } 13 | 14 | default void print() { } 15 | 16 | default void beforePerform(MemoryCell cell, BrainfuckRunner runner, Syntax command) { } 17 | default void afterPerform(MemoryCell cell, BrainfuckRunner runner, Syntax command) { } 18 | 19 | default void beforeWhile(MemoryCell cell, BrainfuckRunner runner) {} 20 | default void afterWhile(MemoryCell cell, BrainfuckRunner runner) {} 21 | default void beforeEndWhile(MemoryCell cell, BrainfuckRunner runner) {} 22 | default void afterEndWhile(MemoryCell cell, BrainfuckRunner runner) {} 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/net/zomis/brainf/ui/tabcontent.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |