diff --git a/src/main/java/net/darmo_creations/ti83_compiler/BinaryFile.java b/src/main/java/net/darmo_creations/ti83_compiler/BinaryFile.java
index 574e631..d3fee61 100644
--- a/src/main/java/net/darmo_creations/ti83_compiler/BinaryFile.java
+++ b/src/main/java/net/darmo_creations/ti83_compiler/BinaryFile.java
@@ -1,11 +1,11 @@
package net.darmo_creations.ti83_compiler;
+import net.darmo_creations.ti83_compiler.utils.ArraysUtil;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import net.darmo_creations.ti83_compiler.utils.ArraysUtil;
-
/**
* This class represents a .8xp program file.
*
@@ -18,14 +18,14 @@ public class BinaryFile {
private boolean editable;
public static final String FORMAT = "8xp";
- public static final String HEADER = "**TI83F*\u001a\n\0";
+ public static final String HEADER = "**TI83F*\u001a\n\n";
public static final String COMMENT = "Created by Java TI-Compiler";
public BinaryFile(String path, String name, byte[] data, boolean editable) {
this.path = path;
- setName(name);
- setData(data);
- setEditable(editable);
+ this.setName(name);
+ this.setData(data);
+ this.setEditable(editable);
}
public String getPath() {
@@ -62,7 +62,7 @@ public void setName(String name) {
/**
* Changes the program's data.
* NOTE: tokens' validity is not checked!
- *
+ *
* @param data the program's data
*/
public void setData(byte[] data) {
@@ -71,7 +71,7 @@ public void setData(byte[] data) {
/**
* Writes the file.
- *
+ *
* @throws IOException if the file could not be written
*/
public void writeFile() throws IOException {
@@ -96,7 +96,7 @@ public void writeFile() throws IOException {
header[57] = (byte) (l & 0x00FF);
header[58] = (byte) ((l & 0xFF00) >> 8);
// Protection
- header[59] = (byte) (isEditable() ? 0x05 : 0x06);
+ header[59] = (byte) (this.isEditable() ? 0x05 : 0x06);
// Program name
ArraysUtil.stringCopy(this.name, header, 60, 8);
// More things
@@ -125,7 +125,7 @@ public void writeFile() throws IOException {
content[content.length - 2] = (byte) (l & 0x00FF);
content[content.length - 1] = (byte) ((l & 0xFF00) >> 8);
- try (FileOutputStream fos = new FileOutputStream(new File(getAbsolutePath()))) {
+ try (FileOutputStream fos = new FileOutputStream(this.getAbsolutePath())) {
fos.write(content);
}
}
diff --git a/src/main/java/net/darmo_creations/ti83_compiler/Main.java b/src/main/java/net/darmo_creations/ti83_compiler/Main.java
index f236bda..0203300 100644
--- a/src/main/java/net/darmo_creations/ti83_compiler/Main.java
+++ b/src/main/java/net/darmo_creations/ti83_compiler/Main.java
@@ -1,12 +1,12 @@
package net.darmo_creations.ti83_compiler;
+import net.darmo_creations.ti83_compiler.compilers.Compiler;
+import net.darmo_creations.ti83_compiler.compilers.Decompiler;
+
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
-import net.darmo_creations.ti83_compiler.compilers.Compiler;
-import net.darmo_creations.ti83_compiler.compilers.Decompiler;
-
public class Main {
public static void main(String[] args) {
System.out.println("** TI-83 Compiler/Decompiler v1.2 **");
@@ -16,8 +16,7 @@ public static void main(String[] args) {
try {
if (argz.size() == 1 && argz.get(0).equals("-h")) {
printUsage(false);
- }
- else {
+ } else {
if (!argz.contains("-f") || argz.indexOf("-f") == argz.size() - 1) {
throw new IllegalArgumentException("No file specified!");
}
@@ -29,41 +28,39 @@ public static void main(String[] args) {
boolean optimise = argz.contains("-O");
boolean editable = !argz.contains("-L");
new Compiler().compile(file, optimise, editable);
- }
- else {
+ } else {
Decompiler decompiler = new Decompiler();
int indexLanguage = argz.indexOf("-u") + 1;
- if (indexLanguage > argz.size() - 1)
+ if (indexLanguage > argz.size() - 1) {
throw new IllegalArgumentException("Missing target language!");
+ }
String lang = argz.get(indexLanguage);
if (argz.contains("-i")) {
int indexIndent = argz.indexOf("-i") + 1;
- if (indexIndent > argz.size() - 1)
+ if (indexIndent > argz.size() - 1) {
throw new IllegalArgumentException("Missing indent size!");
+ }
int indentSize;
try {
indentSize = Integer.parseInt(argz.get(indexIndent));
- if (indentSize < 0)
+ if (indentSize < 0) {
throw new IllegalArgumentException("Indent size must be a positive integer!");
+ }
decompiler.decompile(file, lang, indentSize);
- }
- catch (NumberFormatException ex) {
+ } catch (NumberFormatException ex) {
throw new IllegalArgumentException("Indent size must be an integer!", ex);
}
- }
- else {
+ } else {
decompiler.decompile(file, lang);
}
}
}
- }
- catch (IllegalArgumentException ex) {
+ } catch (IllegalArgumentException ex) {
System.err.println(ex.getMessage());
printUsage(true);
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
@@ -85,4 +82,4 @@ private static void printUsage(boolean error) {
out.println("\tshow this help");
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/net/darmo_creations/ti83_compiler/compilers/BinaryFileParser.java b/src/main/java/net/darmo_creations/ti83_compiler/compilers/BinaryFileParser.java
index 065a376..8ca1ae9 100644
--- a/src/main/java/net/darmo_creations/ti83_compiler/compilers/BinaryFileParser.java
+++ b/src/main/java/net/darmo_creations/ti83_compiler/compilers/BinaryFileParser.java
@@ -1,14 +1,14 @@
package net.darmo_creations.ti83_compiler.compilers;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
import net.darmo_creations.ti83_compiler.BinaryFile;
import net.darmo_creations.ti83_compiler.exceptions.FileFormatException;
import net.darmo_creations.ti83_compiler.exceptions.UnknownTokenException;
import net.darmo_creations.ti83_compiler.utils.ArraysUtil;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
/**
* This class parses a .8xp file into a source code text file.
*
@@ -18,8 +18,8 @@ class BinaryFileParser {
public static final int DEFAULT_INDENT_SIZE = 4;
private final byte[] header;
- private String language;
- private int indentSize;
+ private final String language;
+ private final int indentSize;
public BinaryFileParser(String language, int indentSize) {
this.header = new byte[11];
@@ -31,35 +31,34 @@ public BinaryFileParser(String language, int indentSize) {
/**
* Parses a .8xp file then returns the corresponding source code. The first line is the program's
* name.
- *
+ *
* @param content the content to parse
* @return the program's source code
- * @throws UnknownTokenException if the parser stumbles upon an unknown token
* @throws FileFormatException if the file is corrupted
*/
- public String[] parse(byte[] content) throws UnknownTokenException, FileFormatException {
+ public String[] parse(byte[] content) throws FileFormatException {
List lines = new ArrayList<>();
try {
// Checks the header.
- if (!checkHeader(content)) {
+ if (!this.checkHeader(content)) {
throw new FileFormatException("Invalid header.");
}
- int length = toInt(content[0x48], content[0x49]);
+ int length = this.toInt(content[0x48], content[0x49]);
// Checks the length.
- if (toInt(content[0x35], content[0x36]) - 19 != length //
- || toInt(content[0x39], content[0x3A]) - 2 != length //
- || toInt(content[0x46], content[0x47]) - 2 != length) {
+ if (this.toInt(content[0x35], content[0x36]) - 19 != length //
+ || this.toInt(content[0x39], content[0x3A]) - 2 != length //
+ || this.toInt(content[0x46], content[0x47]) - 2 != length) {
throw new FileFormatException("Invalid length.");
}
// Gets the name.
- lines.add(getName(content));
+ lines.add(this.getName(content));
// Checksum.
- if (!checkSum(content)) {
+ if (!this.checkSum(content)) {
System.err.println("WARNING: invalid checksum, the file may be corrupted.");
System.err.println("We will still attempt to open it.");
System.err.println();
@@ -78,20 +77,19 @@ public String[] parse(byte[] content) throws UnknownTokenException, FileFormatEx
lines.add(indent + currentLine);
if (increaseIndent) {
- indent = addIndent(indent);
+ indent = this.addIndent(indent);
increaseIndent = false;
}
if (newLineAfterIf) {
- indent = removeIndent(indent);
+ indent = this.removeIndent(indent);
newLineAfterIf = false;
}
if (inIfWithoutThen) {
- indent = addIndent(indent);
+ indent = this.addIndent(indent);
inIfWithoutThen = false;
newLineAfterIf = true;
}
currentLine = "";
- found = true;
continue;
}
@@ -115,7 +113,7 @@ else if (token.getInstruction().equals("If ")) {
// else, decrease current indent then re-increase indent.
else if (token.getInstruction().equals("Then")) {
if (newLineAfterIf) {
- indent = removeIndent(indent);
+ indent = this.removeIndent(indent);
newLineAfterIf = false;
}
inIfWithoutThen = false;
@@ -123,12 +121,12 @@ else if (token.getInstruction().equals("Then")) {
}
// Else detected. Decrease current indent then increase indent.
else if (token.getInstruction().equals("Else")) {
- indent = removeIndent(indent);
+ indent = this.removeIndent(indent);
increaseIndent = true;
}
// End detected. Decrease current indent.
else if (token.getInstruction().equals("End")) {
- indent = removeIndent(indent);
+ indent = this.removeIndent(indent);
}
// If the instruction after an if is on the same line.
// E.g.: 'If B:Disp B'
@@ -153,10 +151,9 @@ else if (inIfWithoutThen && token.getInstruction().equals(":")) {
}
}
- return lines.toArray(new String[lines.size()]);
- }
- catch (Exception ex) {
- throw new FileFormatException("Corrupted file.", ex);
+ return lines.toArray(new String[0]);
+ } catch (Exception ex) {
+ throw new FileFormatException("Corrupted file: " + ex.getMessage(), ex);
}
}
@@ -165,9 +162,7 @@ else if (inIfWithoutThen && token.getInstruction().equals(":")) {
*/
private boolean checkHeader(final byte[] bytes) {
byte[] header = new byte[11];
-
System.arraycopy(bytes, 0, header, 0, 11);
-
return Arrays.equals(header, this.header);
}
@@ -175,13 +170,13 @@ private boolean checkHeader(final byte[] bytes) {
* Returns the program's name.
*/
private String getName(byte[] bytes) {
- String name = "";
+ StringBuilder name = new StringBuilder();
for (int i = 0x3C; i < 0x3C + 8 && bytes[i] != 0; i++) {
- name += (bytes[i] == 0x5B) ? 'θ' : (char) bytes[i];
+ name.append((bytes[i] == 0x5B) ? 'θ' : (char) bytes[i]);
}
- return name;
+ return name.toString();
}
/**
@@ -194,7 +189,7 @@ private boolean checkSum(byte[] bytes) {
sum += (bytes[i] < 0) ? bytes[i] + 256 : bytes[i];
}
- return (sum & 0xFFFF) == toInt(bytes[bytes.length - 2], bytes[bytes.length - 1]);
+ return (sum & 0xFFFF) == this.toInt(bytes[bytes.length - 2], bytes[bytes.length - 1]);
}
/**
@@ -218,8 +213,9 @@ private String addIndent(String indent) {
* Removes an indent level.
*/
private String removeIndent(String indent) {
- if (indent.length() < this.indentSize)
+ if (indent.length() < this.indentSize) {
return "";
+ }
return indent.substring(0, indent.length() - this.indentSize);
}
}
diff --git a/src/main/java/net/darmo_creations/ti83_compiler/compilers/Compiler.java b/src/main/java/net/darmo_creations/ti83_compiler/compilers/Compiler.java
index 099f67c..54eb133 100644
--- a/src/main/java/net/darmo_creations/ti83_compiler/compilers/Compiler.java
+++ b/src/main/java/net/darmo_creations/ti83_compiler/compilers/Compiler.java
@@ -1,5 +1,9 @@
package net.darmo_creations.ti83_compiler.compilers;
+import net.darmo_creations.ti83_compiler.BinaryFile;
+import net.darmo_creations.ti83_compiler.exceptions.FileFormatException;
+import net.darmo_creations.ti83_compiler.exceptions.UnknownInstructionException;
+
import java.io.File;
import java.io.IOException;
import java.nio.charset.MalformedInputException;
@@ -8,15 +12,11 @@
import java.nio.file.Paths;
import java.util.List;
-import net.darmo_creations.ti83_compiler.BinaryFile;
-import net.darmo_creations.ti83_compiler.exceptions.FileFormatException;
-import net.darmo_creations.ti83_compiler.exceptions.UnknownInstructionException;
-
public class Compiler {
/**
* Compiles the given file.
- *
- * @param path the path to the file
+ *
+ * @param path the path to the file
* @param optimise if true, the compiled program will be optimised
* @throws IOException
* @throws FileFormatException
@@ -26,28 +26,27 @@ public void compile(String path, boolean optimise, boolean editable) throws IOEx
String progName;
String[] srcCode;
- f = new File(path);
+ f = new File(path).getAbsoluteFile();
- if (!f.getName().substring(f.getName().indexOf('.') + 1).toUpperCase().matches("TI83(EN|FR)?"))
+ if (!f.getName().substring(f.getName().indexOf('.') + 1).toUpperCase().matches("TI83(EN|FR)?")) {
throw new FileFormatException("Unsupported file format.");
- if (!f.exists())
+ }
+ if (!f.exists()) {
throw new IOException("File does not exist!");
+ }
progName = f.getName().substring(0, f.getName().indexOf(".")).toUpperCase();
- srcCode = getSourceCode(f);
+ srcCode = this.getSourceCode(f);
byte[] data;
try {
data = new SourceCodeParser().parse(srcCode, optimise);
- }
- catch (UnknownInstructionException ex) {
- String offset = "\n";
-
+ } catch (UnknownInstructionException ex) {
+ StringBuilder offset = new StringBuilder("\n");
for (int i = 0; i < ex.getColumnOffset() - 1; i++) {
- offset += " ";
+ offset.append(" ");
}
-
throw new RuntimeException("Unknown token at line " + ex.getErrorOffset() + ":\n" + ex.getMessage() + offset + "^", ex);
}
@@ -55,8 +54,7 @@ public void compile(String path, boolean optimise, boolean editable) throws IOEx
try {
bf.writeFile();
- }
- catch (IOException ex) {
+ } catch (IOException ex) {
throw new IOException("Could not write file " + ex.getMessage(), ex);
}
@@ -70,13 +68,10 @@ public void compile(String path, boolean optimise, boolean editable) throws IOEx
private String[] getSourceCode(File file) throws IOException {
try {
List lines = Files.readAllLines(Paths.get(file.getAbsolutePath()));
-
- return lines.toArray(new String[lines.size()]);
- }
- catch (NullPointerException | InvalidPathException | SecurityException ex) {
+ return lines.toArray(new String[0]);
+ } catch (NullPointerException | InvalidPathException | SecurityException ex) {
throw new IOException("Could not open file.", ex);
- }
- catch (MalformedInputException ex) {
+ } catch (MalformedInputException ex) {
throw new IOException("Unsupported encoding! Source files must be encoded in UTF-8.");
}
}
diff --git a/src/main/java/net/darmo_creations/ti83_compiler/compilers/Decompiler.java b/src/main/java/net/darmo_creations/ti83_compiler/compilers/Decompiler.java
index 839cb81..c2dc736 100644
--- a/src/main/java/net/darmo_creations/ti83_compiler/compilers/Decompiler.java
+++ b/src/main/java/net/darmo_creations/ti83_compiler/compilers/Decompiler.java
@@ -29,7 +29,7 @@ public void decompile(String path, String language) throws FileFormatException,
* @param indentSize indentation size
* @throws FileFormatException
*/
- public void decompile(String path, String language, int indentSize) throws FileFormatException, UnknownTokenException, IOException {
+ public void decompile(String path, String language, int indentSize) throws FileFormatException, IOException {
File f;
String progName;
String[] lines;
@@ -38,7 +38,7 @@ public void decompile(String path, String language, int indentSize) throws FileF
throw new IllegalArgumentException("Unknown language " + language);
}
- f = new File(path);
+ f = new File(path).getAbsoluteFile();
if (!f.getName().substring(f.getName().indexOf('.') + 1).toUpperCase().matches("8XP"))
throw new FileFormatException("Unsupported file format.");
diff --git a/src/main/java/net/darmo_creations/ti83_compiler/compilers/SourceCodeParser.java b/src/main/java/net/darmo_creations/ti83_compiler/compilers/SourceCodeParser.java
index 81580ff..61293da 100644
--- a/src/main/java/net/darmo_creations/ti83_compiler/compilers/SourceCodeParser.java
+++ b/src/main/java/net/darmo_creations/ti83_compiler/compilers/SourceCodeParser.java
@@ -1,31 +1,32 @@
package net.darmo_creations.ti83_compiler.compilers;
+import net.darmo_creations.ti83_compiler.exceptions.UnknownInstructionException;
+
import java.util.ArrayList;
import java.util.List;
-import net.darmo_creations.ti83_compiler.exceptions.UnknownInstructionException;
-
class SourceCodeParser {
/**
* Parses the given source code then returns the corresponding tokens.
- *
- * @param srcCode the source code
+ *
+ * @param srcCode the source code
* @param optimise if true, the compiled program will be optimised
* @return the tokens
* @throws UnknownInstructionException
*/
public byte[] parse(String[] srcCode, boolean optimise) throws UnknownInstructionException {
- trim(srcCode);
+ this.trim(srcCode);
// Used to show the parse errors.
final String[] errorSource = new String[srcCode.length];
System.arraycopy(srcCode, 0, errorSource, 0, srcCode.length);
- replaceTags(srcCode);
+ this.replaceTags(srcCode);
- List tokens = extractTokens(srcCode, errorSource);
+ List tokens = this.extractTokens(srcCode, errorSource);
- if (optimise)
- optimise(tokens);
+ if (optimise) {
+ this.optimise(tokens);
+ }
List bytes = new ArrayList<>();
@@ -70,13 +71,11 @@ private List extractTokens(String[] srcCode, String[] errorSource) throws
if (line.charAt(index) == '#') {
index = line.length();
found = true;
- }
- else if (line.charAt(index) == '\\') {
+ } else if (line.charAt(index) == '\\') {
escapeNext = true;
index++;
found = true;
- }
- else {
+ } else {
// Parsing one token
for (Token token : Tokens.TOKENS) {
String instr = token.getInstruction();
@@ -85,7 +84,7 @@ else if (line.charAt(index) == '\\') {
continue;
}
- if (line.substring(index, index + instr.length()).equals(instr)) {
+ if (line.startsWith(instr, index)) {
tokens.add(token);
escapeNext = false;
@@ -134,8 +133,9 @@ private void optimise(List tokens) {
ignoreToken |= !inString && (token.equals(closedParenthesis) && next != null && next.equals(columns)
|| token.equals(star) && (previous != null && !Tokens.isDigit(previous) || next != null && !Tokens.isDigit(next)));
- if (!inString && token.equals(star) && (previous != null && Tokens.isNewLine(previous) || next != null && Tokens.isNewLine(next)))
+ if (!inString && token.equals(star) && (previous != null && Tokens.isNewLine(previous) || next != null && Tokens.isNewLine(next))) {
ignoreToken = false;
+ }
if (ignoreToken) {
changed = true;
@@ -143,10 +143,12 @@ private void optimise(List tokens) {
i--;
}
- if (token.equals(quote))
+ if (token.equals(quote)) {
inString = !inString;
- if (token.equals(Tokens.LINE_END) || token.equals(arrow))
+ }
+ if (token.equals(Tokens.LINE_END) || token.equals(arrow)) {
inString = false;
+ }
}
} while (changed);
}