diff --git a/.idea/intellij-javadocs-4.0.1.xml b/.idea/intellij-javadocs-4.0.1.xml new file mode 100644 index 0000000000000000000000000000000000000000..90d334761db2acb26b9908ca498ccc258f3aba18 --- /dev/null +++ b/.idea/intellij-javadocs-4.0.1.xml @@ -0,0 +1,204 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="JavaDocConfiguration"> + <GENERAL> + <MODE>UPDATE</MODE> + <OVERRIDDEN_METHODS>false</OVERRIDDEN_METHODS> + <SPLITTED_CLASS_NAME>true</SPLITTED_CLASS_NAME> + <LEVELS> + <LEVEL>FIELD</LEVEL> + <LEVEL>METHOD</LEVEL> + <LEVEL>TYPE</LEVEL> + </LEVELS> + <VISIBILITIES> + <VISIBILITY>PUBLIC</VISIBILITY> + <VISIBILITY>PROTECTED</VISIBILITY> + <VISIBILITY>DEFAULT</VISIBILITY> + </VISIBILITIES> + </GENERAL> + <TEMPLATES> + <CLASSES> + <CLASS> + <KEY>^.*(public|protected|private)*.+interface\s+\w+.*</KEY> + <VALUE>/**\n + * The interface ${name}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> + */</VALUE> + </CLASS> + <CLASS> + <KEY>^.*(public|protected|private)*.+enum\s+\w+.*</KEY> + <VALUE>/**\n + * The enum ${name}.\n + */</VALUE> + </CLASS> + <CLASS> + <KEY>^.*(public|protected|private)*.+class\s+\w+.*</KEY> + <VALUE>/**\n + * The type ${name}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> + */</VALUE> + </CLASS> + <CLASS> + <KEY>.+</KEY> + <VALUE>/**\n + * The type ${name}.\n + */</VALUE> + </CLASS> + </CLASSES> + <CONSTRUCTORS> + <CONSTRUCTOR> + <KEY>.+</KEY> + <VALUE>/**\n + * Instantiates a new ${name}.\n +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */</VALUE> + </CONSTRUCTOR> + </CONSTRUCTORS> + <METHODS> + <METHOD> + <KEY>^.*(public|protected|private)*\s*.*(\w(\s*<.+>)*)+\s+get\w+\s*\(.*\).+</KEY> + <VALUE>/**\n + * Gets ${partName}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${partName}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */</VALUE> + </METHOD> + <METHOD> + <KEY>^.*(public|protected|private)*\s*.*(void|\w(\s*<.+>)*)+\s+set\w+\s*\(.*\).+</KEY> + <VALUE>/**\n + * Sets ${partName}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${partName}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */</VALUE> + </METHOD> + <METHOD> + <KEY>^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+</KEY> + <VALUE>/**\n + * The entry point of application.\n + + <#if element.parameterList.parameters?has_content> + *\n +</#if> + * @param ${element.parameterList.parameters[0].name} the input arguments\n +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */</VALUE> + </METHOD> + <METHOD> + <KEY>.+</KEY> + <VALUE>/**\n + * ${name}<#if isNotVoid> ${return}</#if>.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${return}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */</VALUE> + </METHOD> + </METHODS> + <FIELDS> + <FIELD> + <KEY>^.*(public|protected|private)*.+static.*(\w\s\w)+.+</KEY> + <VALUE>/**\n + * The constant ${element.getName()}.\n + */</VALUE> + </FIELD> + <FIELD> + <KEY>^.*(public|protected|private)*.*(\w\s\w)+.+</KEY> + <VALUE>/**\n + <#if element.parent.isInterface()> + * The constant ${element.getName()}.\n +<#else> + * The ${name}.\n +</#if> */</VALUE> + </FIELD> + <FIELD> + <KEY>.+</KEY> + <VALUE>/**\n + <#if element.parent.isEnum()> + *${name} ${typeName}.\n +<#else> + * The ${name}.\n +</#if>*/</VALUE> + </FIELD> + </FIELDS> + </TEMPLATES> + </component> +</project> \ No newline at end of file diff --git a/out/production/Space Cowboys/Test1.class b/out/production/Space Cowboys/Test1.class deleted file mode 100644 index eae931181a00a1762e70d2f399d3cfaff1a0aa32..0000000000000000000000000000000000000000 Binary files a/out/production/Space Cowboys/Test1.class and /dev/null differ diff --git a/out/production/Space Cowboys/Test2.class b/out/production/Space Cowboys/Test2.class deleted file mode 100644 index 27388d7eee6087756af0511f757d52fa34b03c49..0000000000000000000000000000000000000000 Binary files a/out/production/Space Cowboys/Test2.class and /dev/null differ diff --git a/src/Expression.java b/src/Expression.java new file mode 100644 index 0000000000000000000000000000000000000000..68630f1a486f03a8c0fa50bade2a55a25eace03c --- /dev/null +++ b/src/Expression.java @@ -0,0 +1,83 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class Expression { + public interface Value<T> { + public T getValue(); + } + + static class IntVal implements Value<Integer> { + Integer v; + + public IntVal(Integer v) { + this.v = v; + } + public Integer getValue() { + return v; + } + } + + static class BoolValue implements Value<Boolean> { + boolean b; + + public BoolValue(boolean b) { + this.b = b; + } + + public Boolean getValue() { + return b; + } + } + + interface Expr { + Value run(ProgramHandler.ProgramState s); + } + + public static class LiteralExpr implements Expr { + Value x; + + @Override + public Value run(ProgramHandler.ProgramState s) { + return x; + } + + public LiteralExpr(Value x) { + this.x = x; + } + } + + static class VarExpr implements Expr { + String name; + + @Override + public Value run(ProgramHandler.ProgramState s) { + return new IntVal(s.varLookup.get(name)); + } + + public VarExpr(String n) { + name = n; + } + } + + static class NotExpr implements Expr { + Expr lhs, rhs; + + public NotExpr(Expr lhs, Expr rhs) { + this.lhs = lhs; + this.rhs = rhs; + } + public Value run(ProgramHandler.ProgramState s) { + Value lhsV = lhs.run(s); + Value rhsV = rhs.run(s); + if (lhsV.getClass() == rhsV.getClass()) { + return new BoolValue(lhsV.getValue() == rhsV.getValue()); + } + return new BoolValue(false); + } + } + + public static class ExpressionBuilder { + List<Expr> x = new ArrayList<Expr>(); + } +} diff --git a/src/Interpreter.java b/src/Interpreter.java new file mode 100644 index 0000000000000000000000000000000000000000..577c933660ae099b2c935ddcbf5e6d7b1f32325a --- /dev/null +++ b/src/Interpreter.java @@ -0,0 +1,31 @@ +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + +public class Interpreter { + public static void main(String[] args) { + try { + // reading the file + File filePath = new File("C:\\Users\\alist\\IdeaProjects\\Space Cowboys\\src\\program.bb"); + Scanner reader = new Scanner(filePath); + StringBuilder data = new StringBuilder(); + // moves the file into a string + while (reader.hasNextLine()) { + data.append(reader.nextLine()); + data.append(" "); + } + reader.close(); + Lexer.LexerContainer container = Lexer.lexer(data.toString().trim().replaceAll(" +", " ")); + ProgramHandler.ProgramState state = new ProgramHandler.ProgramState(); + ProgramHandler.Program program = Parser.parse(container); + program.run(state); + for (Map.Entry<String, Integer> entry : state.varLookup.entrySet()) { + System.out.println("Variable: " + entry.getKey() + ", Value: " + entry.getValue()); + } + } + catch (FileNotFoundException e){ + System.out.println("File can't be found."); + e.printStackTrace(); + } + } +} diff --git a/src/Lexer.java b/src/Lexer.java new file mode 100644 index 0000000000000000000000000000000000000000..d588bd621201fb973fcb8de124b1a3f693c90fc6 --- /dev/null +++ b/src/Lexer.java @@ -0,0 +1,74 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class Lexer { + + public static class LexerContainer { + public List<Token> tokens; + List<String> vars; + public LexerContainer(List<Token> tokens, List<String> vars) { + this.tokens = tokens; + this.vars = vars; + } + } + + /** + * @param file the file to be processed + * @return list of tokens produced by the lexer + */ + public static LexerContainer lexer(String file) { + List<Token> tokens = new ArrayList<Token>(); + List<String> vars = new ArrayList<>(); + int previousChar = 0; + for (int currentChar = 0; currentChar < file.length(); currentChar++) { + if (file.charAt(currentChar) == ' ' || file.charAt(currentChar) == ';') { + String x = ""; + if (previousChar == currentChar) { + x = "" + file.charAt(previousChar); + } + else { + x = file.substring(previousChar, currentChar).replaceAll(" ", ""); + } + switch (x) { + case ("clear") -> { + tokens.add(Token.Clear); + } + case ("incr") -> { + tokens.add(Token.Incr); + } + case ("decr") -> { + tokens.add(Token.Decr); + } + case ("while") -> { + tokens.add(Token.While); + } + case ("do") -> { + tokens.add(Token.Do); + } + case ("not") -> { + tokens.add(Token.Not); + } + case (";") -> { + tokens.add(Token.SemiColon); + } + case ("end") -> { + tokens.add(Token.End); + } + default -> { + if (x.matches("[0-9]+")) { + tokens.add(Token.Number); + vars.add(x); + } + else if (x.matches("[a-zA-Z]+")) { + tokens.add(Token.Var); + vars.add(x); + } + } + } + previousChar = currentChar; + } + } + return new LexerContainer(tokens, vars); + } +} diff --git a/src/Pair.java b/src/Pair.java new file mode 100644 index 0000000000000000000000000000000000000000..1a10efcf79ea3dc6cb9655b047b635e5a8f845a6 --- /dev/null +++ b/src/Pair.java @@ -0,0 +1,9 @@ +public class Pair<T, K> { + T first; + K second; + + public Pair(T t, K k) { + first = t; + second = k; + } +} diff --git a/src/Parser.java b/src/Parser.java new file mode 100644 index 0000000000000000000000000000000000000000..c3a1e9de8cf94b984d4734a5aad5e24d94c66358 --- /dev/null +++ b/src/Parser.java @@ -0,0 +1,97 @@ +import java.util.List; + +public class Parser { + public static ProgramHandler.Program parse(Lexer.LexerContainer container) { + List<Token> tokens = container.tokens; + List<String> vars = container.vars; + + ProgramHandler.Program program = new ProgramHandler.Program(); + + while (!tokens.isEmpty()) { + Token token = tokens.remove(0); + if (token != Token.SemiColon) { + switch (token) { + case Clear -> { + if (tokens.remove(0) == Token.Var) { + ProgramHandler.ClearStatement statement = new ProgramHandler.ClearStatement(); + statement.v = new ProgramHandler.Variable(vars.remove(0)); + program.stmts.add(statement); + } else { + System.err.println("Clear not followed by variable"); + } + } + case Incr -> { + if (tokens.remove(0) == Token.Var) { + ProgramHandler.IncrStatement statement = new ProgramHandler.IncrStatement(); + statement.v = new ProgramHandler.Variable(vars.remove(0)); + program.stmts.add(statement); + } else { + System.err.println("Incr not followed by variable"); + } + } + case Decr -> { + if (tokens.remove(0) == Token.Var) { + ProgramHandler.DecrStatement statement = new ProgramHandler.DecrStatement(); + statement.v = new ProgramHandler.Variable(vars.remove(0)); + program.stmts.add(statement); + } else { + System.err.println("Decr not followed by variable"); + } + } + case While -> { + ProgramHandler.WhileLoop loop = new ProgramHandler.WhileLoop(); + Expression.Expr expr = eParse(container); + loop.expr = expr; + loop.p = parse(container); + program.stmts.add(loop); + } + case End -> { + return program; + } + case Var, Number -> { + System.err.println("Something went wrong, L for u. " + token + " " + tokens.get(0)); + } + } + } + } + + return program; + } + + private static Expression.Expr eParse(Lexer.LexerContainer container){ + List<Token> tokens = container.tokens; + List<String> vars = container.vars; + Expression.Expr e = null; + + while (!tokens.isEmpty()) { + Token token = tokens.remove(0); + switch (token) { + case Var -> { + if (e == null) { + e = new Expression.VarExpr(vars.remove(0)); + } else { + System.err.println("Expression not valid"); + System.exit(1); + } + } case Number -> { + if (e == null) { + e = new Expression.LiteralExpr(new Expression.IntVal(Integer.parseInt(vars.remove(0)))); + } else { + System.err.println("Expression not valid"); + System.exit(1); + } + } case Not -> { + if (e != null) { + Expression.Expr rhs = eParse(container); + e = new Expression.NotExpr(e, rhs); + } + } case Do, End, SemiColon -> { + return e; + } + } + } + System.err.println("Expr never ended"); + System.exit(1); + return new Expression.LiteralExpr(new Expression.IntVal(1)); + } +} diff --git a/src/ProgramHandler.java b/src/ProgramHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..fbd7b8d3a7fee4a6f20dfdc6293078976c22122a --- /dev/null +++ b/src/ProgramHandler.java @@ -0,0 +1,110 @@ +import java.util.*; + +public class ProgramHandler { + private static ProgramHandler single_instance = null; + + private ProgramHandler() { + } + + public static class Variable { + String name; + + Variable(String n) { + name = n; + } + } + + public static ProgramHandler getInstance() { + if (single_instance == null) + single_instance = new ProgramHandler(); + + return single_instance; + } + + interface Runnable { + public void run(ProgramState state); + } + + static class Statement implements Runnable { + @Override + public void run(ProgramState state) { + + } + } + + static class ProgramState { + public HashMap<String, Integer> varLookup = new HashMap<>(); + + public HashMap<String, Integer> getState() { + return varLookup; + } + } + + static class Program implements Runnable { + public List<Statement> stmts = new ArrayList<Statement>(); + + @Override + public void run(ProgramState state) { + for (Statement statement : stmts) { + statement.run(state); + } + } + } + + static class ClearStatement extends Statement { + public Variable v; + + @Override + public void run(ProgramState state) { + if (!state.varLookup.containsKey(v.name)) { + state.varLookup.put(v.name, 0); + } else { + state.varLookup.replace(v.name, 0); + } + } + } + + static class IncrStatement extends Statement { + public Variable v; + + @Override + public void run(ProgramState state) { + if (state.varLookup.containsKey(v.name)) { + int curr = state.varLookup.get(v.name); + state.varLookup.replace(v.name, curr + 1); + } + } + } + + static class DecrStatement extends Statement { + public Variable v; + + @Override + public void run(ProgramState state) { + if (state.varLookup.containsKey(v.name)) { + int curr = state.varLookup.get(v.name); + state.varLookup.replace(v.name, curr - 1); + } + } + } + + static class WhileLoop extends Statement { + public Program p; + public Expression.Expr expr; + + @Override + public void run(ProgramState state) { + Expression.Value val = expr.run(state); + Expression.BoolValue boolValue = val instanceof Expression.BoolValue ? ((Expression.BoolValue) val) : null; + if (boolValue != null) { + if (!boolValue.b) { + p.run(state); + run(state); + } + } else { + System.err.println("Wrong Expression Type"); + } + } + + } +} diff --git a/src/Test1.java b/src/Test1.java deleted file mode 100644 index d6a891dbf43b0c2906684637f1808e58db3c83f1..0000000000000000000000000000000000000000 --- a/src/Test1.java +++ /dev/null @@ -1,6 +0,0 @@ -public class Test1 { - public static void main(String[] args) { - Test2 test = new Test2(1, 2, "abc"); - System.out.println(test.print()); - } -} diff --git a/src/Test2.java b/src/Test2.java deleted file mode 100644 index 0ff8da2329e866dfab43541a6fb2dc1682a9b146..0000000000000000000000000000000000000000 --- a/src/Test2.java +++ /dev/null @@ -1,16 +0,0 @@ -public class Test2 { - int x; - int y; - String z; - public Test2(int a, int b, String c) { - x = a; - y = b; - z = c; - } - public String print() { - return x + " " + y + " " + " " + z; - } - public void error() { - java.lang.System.err.println("test " + x); - } -} diff --git a/src/Token.java b/src/Token.java new file mode 100644 index 0000000000000000000000000000000000000000..d715d491a7a68bf8c7d690501ed36332de7abf0a --- /dev/null +++ b/src/Token.java @@ -0,0 +1,12 @@ +public enum Token { + Clear, + Incr, + Decr, + While, + Do, + Not, + Var, + SemiColon, + Number, + End +} \ No newline at end of file diff --git a/src/program.bb b/src/program.bb new file mode 100644 index 0000000000000000000000000000000000000000..d088686cf58265a805a553ab110c8986aa740ef3 --- /dev/null +++ b/src/program.bb @@ -0,0 +1,13 @@ +clear X; +clear Y; +incr Y; +clear jakub; +while jakub not 7 do; + incr jakub; +end; +incr X; +incr X; +incr X; +while X not 0 do; + decr X; +end; \ No newline at end of file