Fixed bug in matrices, refactored B2C
This commit is contained in:
parent
f77d90b9c2
commit
d56af7f194
|
@ -99,7 +99,7 @@ BCDvar *B2C_sub(BCDvar *buffer, BCDvar *a, BCDvar *b) {
|
|||
unsigned char tempByte;
|
||||
int result[15] = {0};
|
||||
//Check for special cases
|
||||
//a < 0 and b < 0 -> b-a
|
||||
//a < 0 and b < 0 -> (-b)-(-a)
|
||||
//Ex: (-4)-(-3) -> 3-4
|
||||
if ((*a)[0] > 0x30 && (*b)[0] > 0x30) {
|
||||
BCDvar a2, b2;
|
||||
|
@ -360,13 +360,22 @@ BCDvar *B2C_xor(BCDvar *a, BCDvar *b) {
|
|||
if (!((*a)[1]) != !((*b)[1])) return &_1_;
|
||||
return &_0_;
|
||||
}
|
||||
|
||||
BCDvar *B2C_int(BCDvar *buffer, BCDvar *a) {
|
||||
const char *function = "\xA6""A";
|
||||
setAlphaVar('A', a);
|
||||
calcExp(&function, dummyOpCode, buffer, 1);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
unsigned char* B2C_convToStr(BCDvar *nb) {
|
||||
bcdToStr(nb, stringBuffer);
|
||||
return stringBuffer;
|
||||
}
|
||||
|
||||
void B2C_setListRow(unsigned int nbList, unsigned int row, BCDvar *value) {
|
||||
memcpy(list[nbList].data[row], *value, 21);
|
||||
memcpy(list[nbList].data[row], *value, sizeof(BCDvar)-3);
|
||||
}
|
||||
|
||||
void B2C_setDimList(unsigned int nbList, unsigned short nbElements) {
|
||||
|
@ -382,20 +391,32 @@ List B2C_newList(int nbElements, ...) {
|
|||
va_start(vaList, nbElements);
|
||||
//memcpy(list.data[0], _0_, sizeof(BCDvar));
|
||||
for (i = 1; i <= nbElements; i++) {
|
||||
memcpy(list.data[i], va_arg(vaList, BCDvar), 21);
|
||||
memcpy(list.data[i], va_arg(vaList, BCDvar), sizeof(BCDvar)-3);
|
||||
}
|
||||
va_end(vaList);
|
||||
return list;
|
||||
}
|
||||
|
||||
void B2C_setDimMat(unsigned char matrix, unsigned short y, unsigned short x) {
|
||||
void B2C_setDimMat(unsigned char matrix, unsigned short x, unsigned short y) {
|
||||
mat[matrix].width = x;
|
||||
mat[matrix].height = y;
|
||||
mat[matrix].data = calloc((y+1)*(x+1), sizeof(BCDvar));
|
||||
mat[matrix].data = calloc(x*y, sizeof(BCDvar));
|
||||
}
|
||||
|
||||
void B2C_setMat(unsigned char matrix, unsigned int y, unsigned int x, BCDvar *value) {
|
||||
memcpy(mat[matrix].data[mat[matrix].width*y+x], *value, 21);
|
||||
void B2C_setMatCase(unsigned char matrix, unsigned int x, unsigned int y, BCDvar *value) {
|
||||
memcpy(mat[matrix].data[mat[matrix].height*(x-1)+y-1], *value, sizeof(BCDvar)-3);
|
||||
}
|
||||
|
||||
void B2C_fillMat(BCDvar *value, unsigned char matrix) {
|
||||
for (i = 0; i < mat[matrix].width*mat[matrix].height; i++) {
|
||||
memcpy(mat[matrix].data[i], *value, sizeof(BCDvar)-3);
|
||||
}
|
||||
}
|
||||
|
||||
void B2C_clrMat(unsigned char matrix) {
|
||||
free(mat[matrix].data);
|
||||
mat[matrix].width = 0;
|
||||
mat[matrix].height = 0;
|
||||
}
|
||||
|
||||
unsigned int B2C_convToUInt(BCDvar *nb) {
|
||||
|
@ -428,7 +449,7 @@ int B2C_convToInt(BCDvar *nb) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
BCDvar *B2C_Getkey() {
|
||||
BCDvar *B2C_getkey() {
|
||||
if (!prgmGetkey(&getkeyBuffer)) {
|
||||
B2C_exit(NO_ERROR);
|
||||
}
|
||||
|
@ -476,6 +497,22 @@ void B2C_exit(int exitCode) {
|
|||
}
|
||||
}
|
||||
|
||||
BCDvar *B2C_rand(BCDvar *buffer) {
|
||||
int randDigit;
|
||||
char tempByte;
|
||||
//Initialise exponent to 99 (-1)
|
||||
(*buffer)[0] = 9;
|
||||
tempByte = 0x90;
|
||||
for (i = 0; i < 15; i++) {
|
||||
if (i%2) {
|
||||
tempByte = (rand()%10) << 4;
|
||||
} else {
|
||||
(*buffer)[(i+1)/2+1] = tempByte + (rand()%10);
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
BCDvar *B2C_ranInt(BCDvar *buffer, BCDvar *a, BCDvar *b) {
|
||||
//A + Int (Ran# * (B - A + 1))
|
||||
const char *function = "A""\x89""\xA6""(""\xC1""\xA9""(B""\x99""A""\x89""1))";
|
||||
|
@ -494,8 +531,8 @@ BCDvar *B2C_calcExp(unsigned char* exp) {
|
|||
calcExp(&exp, dummyOpCode, &expressionBuffer, 1);
|
||||
return &expressionBuffer;
|
||||
}
|
||||
void B2C_setAlphaVar(unsigned char variable, BCDvar *value) {
|
||||
memcpy(var[variable], *value, 21);
|
||||
void B2C_setAlphaVar(BCDvar *alphaVar, BCDvar *value) {
|
||||
memcpy(*alphaVar, *value, sizeof(BCDvar)-3);
|
||||
}
|
||||
void B2C_setStr(Str *value, int isString, int strNum) {
|
||||
free(strings[strNum].data);
|
||||
|
@ -602,13 +639,9 @@ Str *B2C_strJoin(Str *str1, Str *str2, int isString1, int isString2) {
|
|||
free_str(str2);
|
||||
return result;
|
||||
}
|
||||
BCDvar *B2C_strLen(Str *str, int isString) {
|
||||
unsigned char length[4] = {0};
|
||||
BCDvar *result;
|
||||
sprintf(length, "%d", str->length);
|
||||
result = B2C_calcExp(length);
|
||||
free_str(str);
|
||||
return result;
|
||||
BCDvar *B2C_strLen(BCDvar *buffer, Str *str, int isString) {
|
||||
intToBCD(str->length, buffer);
|
||||
return buffer;
|
||||
}
|
||||
Str *B2C_strMid(Str *str, int isString, int start, int offset) {
|
||||
Str *result = malloc(sizeof(Str));
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.nio.file.Files;
|
|||
import java.nio.file.StandardCopyOption;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
|
||||
/* TODO 's:
|
||||
|
@ -18,8 +19,8 @@ public class B2C {
|
|||
final static boolean debugMode = true;
|
||||
|
||||
static String path = "C:\\Users\\Catherine\\Documents\\CASIO\\fx-9860G SDK\\TestB2C\\";
|
||||
static String mainProgramName = "__uiss4_";
|
||||
static String pathToG1M = "C:\\Users\\Catherine\\Desktop\\puiss4.g1m";
|
||||
static String mainProgramName = "DEMNR";
|
||||
static String pathToG1M = "C:\\Users\\Catherine\\Desktop\\goldroad.g2m";
|
||||
static boolean isRealTimeGame = true;
|
||||
static boolean assureOS1Compatibility = true;
|
||||
static boolean usesAcOnTimer = true;
|
||||
|
@ -84,6 +85,7 @@ public class B2C {
|
|||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
Operators.initOperators();
|
||||
//Add some constants for functions
|
||||
Constants.add("0");
|
||||
Constants.add("1");
|
||||
|
@ -107,7 +109,7 @@ public class B2C {
|
|||
"int i;\n"+
|
||||
"BCDvar var[29] = {0}; //A-Z, r, theta, Ans\n"+
|
||||
"Str strings[20];\n" +
|
||||
"Mat mat[26]; //Important thing: matrixes are (height, width) not (width, height)\n" +
|
||||
"Mat mat[27]; //Important thing: matrixes are (height, width) not (width, height)\n" +
|
||||
"List list[26];\n" +
|
||||
"char dummyOpCode[2] = {5, 8};\n" +
|
||||
"//These are buffers for syscalls that do not return a value.\n" +
|
||||
|
@ -124,6 +126,7 @@ public class B2C {
|
|||
"\tfor (i = 0; i < 20; i++) {\n" +
|
||||
"\t\tstrings[i].length = 0;\n" +
|
||||
"\t}\n" +
|
||||
"\tsrand((unsigned int)" + new Random().nextInt() + ");\n" +
|
||||
"\t#ifdef USES_INTERRUPTION_TIMER\n" +
|
||||
"\t//Timer allowing AC/ON to be pressed at any moment\n" +
|
||||
"\tSetTimer(INTERRUPTION_TIMER, 50, (void (*)(void))exitTimerHandler);\n" +
|
||||
|
@ -201,9 +204,9 @@ public class B2C {
|
|||
for (int i = 0; i <= 1; i++) {
|
||||
IO.writeToFile(new File(path+externalLibs[i]), IO.readFromRelativeFile(externalLibs[i]), true);
|
||||
}
|
||||
for (char c = 'A'; c <= 'Z'; c++) {
|
||||
Header.addDefine(c+" "+(int)c);
|
||||
}
|
||||
/*for (char c = 'A'; c <= 'Z'; c++) {
|
||||
Header.addDefine(c+" "+(c-'A'));
|
||||
}*/
|
||||
Header.addDefine("FALSE 0");
|
||||
Header.addDefine("TRUE 1");
|
||||
Header.addDefine("A_GREATER_THAN_B 1");
|
||||
|
@ -232,7 +235,7 @@ public class B2C {
|
|||
|
||||
Header.addDefine("free_str(x) if(!isString){free(x->data); free(x);}");
|
||||
Header.addDefine("getDigit(BCDvar, i) (((i)%2) ? (*(BCDvar))[((i)+1)/2+1]>>4 : (*(BCDvar))[((i)+1)/2+1]&0x0F)");
|
||||
Header.addDefine("getExp(BCDvar) (((*(a))[0]>>4) * 100 + ((*(a))[0]&0x0F) * 10 + ((*(a))[1]>>4))");
|
||||
Header.addDefine("getExp(BCDvar) (((*(BCDvar))[0]>>4) * 100 + ((*(BCDvar))[0]&0x0F) * 10 + ((*(BCDvar))[1]>>4))");
|
||||
Header.create();
|
||||
|
||||
System.out.println("Parsing done in " + (System.currentTimeMillis()-startTime) + " ms.");
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.ArrayList;
|
|||
|
||||
public class Constants {
|
||||
|
||||
static ArrayList<Double> consts = new ArrayList<Double>();
|
||||
static ArrayList<String> consts = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* This method is to optimise the speed of B2C by pre-calculating constants.
|
||||
|
@ -12,15 +12,33 @@ public class Constants {
|
|||
* special things like 1e5, 1/3, etc.
|
||||
*/
|
||||
public static void add(String constant) {
|
||||
constant = constant.replaceAll("\\x99", "-");
|
||||
constant = constant.replaceAll("\\x99|\\x87", "-");
|
||||
//System.out.println(constant);
|
||||
if (constant.startsWith(".")) {
|
||||
constant = "0" + constant;
|
||||
//Interpret "." as "0.", example: -.5 = -0.5
|
||||
constant = constant.replaceAll("(?<!\\d)\\.", "0.");
|
||||
|
||||
//Remove last ".", example: 85. = 85.0 = 85
|
||||
if (constant.charAt(constant.length()-1) == '.') {
|
||||
constant = constant.substring(0, constant.length()-1);
|
||||
}
|
||||
if (consts.contains(Double.valueOf(constant))) {
|
||||
|
||||
//Parse special operators
|
||||
//sqrt
|
||||
if (constant.startsWith(new String(new char[]{0x86}))) {
|
||||
String sqrt = String.valueOf(Math.sqrt(Double.valueOf(constant.substring(1))));
|
||||
if (sqrt.length() > 15) {
|
||||
sqrt = sqrt.substring(0, 15);
|
||||
}
|
||||
add(sqrt);
|
||||
}
|
||||
|
||||
if (!isNumber(constant)) {
|
||||
Parser.error("Constant " + Parser.printNonAscii(constant) + " is not a number!");
|
||||
}
|
||||
if (consts.contains(constant)) {
|
||||
return;
|
||||
}
|
||||
consts.add(Double.valueOf(constant));
|
||||
consts.add(constant);
|
||||
//Calculate the bytes of the constant
|
||||
//Note: can't convert to double due to precision loss
|
||||
//To fix this, we remove the decimal point to convert to integer and keep the exponent
|
||||
|
@ -60,13 +78,32 @@ public class Constants {
|
|||
//System.out.println("Result= "+bcdNotation);
|
||||
//Replace groups of 2 digits by "0x##, " and remove the last comma+space
|
||||
//System.out.println(bcdNotation);
|
||||
|
||||
//Handle the special case of 0
|
||||
if (Double.valueOf(constant) == 0) {
|
||||
bcdNotation = "000000000000000000"; //18 0s
|
||||
}
|
||||
bcdNotation = bcdNotation.replaceAll("(.{2})", "0x$1, ").replaceAll(", $", "");
|
||||
//System.out.println(bcdNotation);
|
||||
Header.addGlobal("const BCDvar " + Constants.getVarNotation(constant) + " = {" + bcdNotation + "};\n");
|
||||
}
|
||||
|
||||
public static String getVarNotation(String nb) {
|
||||
return "_"+nb.replaceAll("\\.|\\-|\\x99", "_")+"_";
|
||||
String result;
|
||||
//System.out.println(nb);
|
||||
result = nb.replaceAll("(?<!\\d)\\.", "0.");
|
||||
//System.out.println(result);
|
||||
result = result.replaceAll("\\.|\\-|\\x99|\\x87", "_");
|
||||
//System.out.println(result);
|
||||
//Remove last "."
|
||||
if (result.charAt(result.length()-1) == '.') {
|
||||
result = result.substring(0, result.length()-1);
|
||||
}
|
||||
return "_" + result + "_";
|
||||
}
|
||||
|
||||
public static boolean isNumber(String nb) {
|
||||
return nb.matches("[\\d\\x99\\x87\\.\\-]+");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -182,6 +182,9 @@ public class Functions {
|
|||
addFunctions();
|
||||
String functionsBuffer = IO.readFromRelativeFile("B2CFunctions.c");
|
||||
Integer[] functionsPositions = Parser.parseBrackets(functionsBuffer);
|
||||
if (functionsPositions.length % 4 != 0) {
|
||||
Parser.error("cannot parse functions! Make sure not to have comments between functions (put them inside)");
|
||||
}
|
||||
|
||||
//System.out.println(functionsBuffer.substring(0, functionsPositions[2]));
|
||||
functions += addMethod(functionsBuffer.substring(0, functionsPositions[3]+1));
|
||||
|
|
|
@ -16,7 +16,6 @@ public class G1MParser {
|
|||
int lastCarriageReturn = -1;
|
||||
Parser.instructions.clear();
|
||||
Parser.instructionNumber = 0;
|
||||
Parser.nbBuffers = 0;
|
||||
|
||||
|
||||
//Divides the instructions
|
||||
|
@ -38,29 +37,35 @@ public class G1MParser {
|
|||
* To avoid creating a buffer at each function call,
|
||||
* as many buffers are created as functions calls in an instruction.
|
||||
*/
|
||||
int nbBuffers = 0;
|
||||
int[] buffers = {0,0,0,0};
|
||||
do {
|
||||
Parser.nbBuffers = 0;
|
||||
for (int i = 0; i < buffers.length; i++) {
|
||||
Parser.buffers[0] = 0;
|
||||
}
|
||||
result.append(Parser.tabs + Parser.parse(Parser.instructions.get(Parser.instructionNumber), Parser.WHOLE_INSTRUCTION) + "\n");
|
||||
Parser.instructionNumber++;
|
||||
if (nbBuffers < Parser.nbBuffers) {
|
||||
nbBuffers = Parser.nbBuffers;
|
||||
for (int i = 0; i < buffers.length; i++) {
|
||||
if (buffers[i] < Parser.buffers[i]) {
|
||||
buffers[i] = Parser.buffers[i];
|
||||
}
|
||||
}
|
||||
} while (Parser.instructionNumber < Parser.instructions.size());
|
||||
|
||||
//Add buffers
|
||||
String buffers = "\tBCDvar ";
|
||||
for (int i = 0; i < nbBuffers; i++) {
|
||||
buffers += "buffer" + i;
|
||||
if (i+1 < nbBuffers) buffers += ", ";
|
||||
for (int h = 0; h < buffers.length; h++) {
|
||||
String bufferStr = "\t" + Parser.bufferTypes[h] + " ";
|
||||
for (int i = 0; i < buffers[h]; i++) {
|
||||
bufferStr += Parser.bufferVars[h] + i;
|
||||
if (i+1 < buffers[h]) bufferStr += ", ";
|
||||
}
|
||||
bufferStr += ";\n";
|
||||
if (buffers[h] > 0) result.insert(0, bufferStr);
|
||||
}
|
||||
buffers += ";\n";
|
||||
if (nbBuffers > 0) result.insert(0, buffers);
|
||||
result.insert(0, "void prog_"+currentProgram+"() {\n");
|
||||
//result = Parser.autoreplace(result);
|
||||
result.append("}");
|
||||
System.out.println("nb buffers = " + nbBuffers);
|
||||
System.out.println(Parser.nbBuffers);
|
||||
//System.out.println("nb buffers = " + nbBuffers);
|
||||
//System.out.println(Parser.nbBuffers);
|
||||
return result.toString();
|
||||
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public class IO {
|
|||
content = content.substring(32);
|
||||
|
||||
//due to unicode encoding, some characters get encoded as others
|
||||
|
||||
|
||||
content = content.replaceAll("\\u2020", new String(new char[]{0x86}));
|
||||
content = content.replaceAll("\\u2021", new String(new char[]{0x87}));
|
||||
content = content.replaceAll("\\u02C6", new String(new char[]{0x88}));
|
||||
|
@ -73,6 +73,7 @@ public class IO {
|
|||
content = content.replaceAll("\\u2122", new String(new char[]{0x99}));
|
||||
content = content.replaceAll("\\u0161", new String(new char[]{0x9A}));
|
||||
content = content.replaceAll("\\u203A", new String(new char[]{0x9B}));
|
||||
content = content.replaceAll("\\u017E", new String(new char[]{0x9E}));
|
||||
//TODO actually parse the g1m
|
||||
String[] programs = content.split("PROGRAM[\\s\\S]{13}system[\\s\\S]{2}");
|
||||
|
||||
|
|
|
@ -3,13 +3,36 @@ package b2c;
|
|||
public class Operator {
|
||||
|
||||
private String casioChar, asciiFunction;
|
||||
private int precedence, nbOperands;
|
||||
private int nbOperands;
|
||||
private boolean isMathematicalFunction;
|
||||
|
||||
public Operator(int nbOperands, String casioChar, String asciiFunction, int precedence) {
|
||||
public boolean isMathematicalFunction() {
|
||||
return this.isMathematicalFunction;
|
||||
}
|
||||
|
||||
public void setMathematicalFunction(boolean isMathematicalFunction) {
|
||||
this.isMathematicalFunction = isMathematicalFunction;
|
||||
}
|
||||
|
||||
public int getNbOperands() {
|
||||
return nbOperands;
|
||||
}
|
||||
|
||||
public void setNbOperands(int nbOperands) {
|
||||
this.nbOperands = nbOperands;
|
||||
}
|
||||
|
||||
public Operator(String casioChar, String asciiFunction, boolean isMathematicalFunction) {
|
||||
this.casioChar = casioChar;
|
||||
this.asciiFunction = asciiFunction;
|
||||
this.precedence = precedence;
|
||||
this.isMathematicalFunction = isMathematicalFunction;
|
||||
}
|
||||
|
||||
public Operator(String casioChar, String asciiFunction, boolean isMathematicalFunction, int nbOperands) {
|
||||
this.casioChar = casioChar;
|
||||
this.asciiFunction = asciiFunction;
|
||||
this.nbOperands = nbOperands;
|
||||
this.isMathematicalFunction = isMathematicalFunction;
|
||||
}
|
||||
|
||||
public String getCasioChar() {
|
||||
|
@ -27,20 +50,4 @@ public class Operator {
|
|||
public void setAsciiFunction(String asciiFunction) {
|
||||
this.asciiFunction = asciiFunction;
|
||||
}
|
||||
|
||||
public int getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
public void setPrecedence(int precedence) {
|
||||
this.precedence = precedence;
|
||||
}
|
||||
|
||||
public int getNbOperands() {
|
||||
return nbOperands;
|
||||
}
|
||||
|
||||
public void setNbOperands(int nbOperands) {
|
||||
this.nbOperands = nbOperands;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,34 +4,43 @@ import java.util.ArrayList;
|
|||
|
||||
public class Operators {
|
||||
|
||||
public static int maxPrecedence = 6;
|
||||
public static int maxPrecedence = 0;
|
||||
//Not sure if the precedence of xor/or is equal or not
|
||||
//Pretty sure about all other precedences; feel free to test
|
||||
//All seem to be left-to-right
|
||||
//All seem to be left-to-right, even equality operators
|
||||
public static Operator[][] operators = {{
|
||||
|
||||
new Operator(1, new String(new char[]{0x7F, 0xB3}), "B2C_not", 0),
|
||||
|
||||
new Operator(new String(new char[]{0xA8}), "B2C_pow", true),
|
||||
new Operator(new String(new char[]{0x86}), "B2C_nthRoot", true),
|
||||
},{
|
||||
new Operator(new String(new char[]{0x99}), "B2C_neg", true, 1),
|
||||
new Operator(new String(new char[]{0x87}), "B2C_neg", true, 1),
|
||||
//new Operator(new String(new char[]{0x89}), "B2C_unaryPlus", false, 1), //unary plus = nothing
|
||||
|
||||
},{
|
||||
new Operator(2, new String(new char[]{0xA8}), "B2C_pow", 1),
|
||||
new Operator(2, new String(new char[]{0x86}), "B2C_sqrt", 1),
|
||||
new Operator(new String(new char[]{0xA9}), "B2C_mult", true),
|
||||
new Operator(new String(new char[]{0xB9}), "B2C_div", true),
|
||||
},{
|
||||
new Operator(2, new String(new char[]{0xA9}), "B2C_mult", 2),
|
||||
new Operator(2, new String(new char[]{0xB9}), "B2C_div", 2),
|
||||
new Operator(new String(new char[]{0x89}), "B2C_add", true),
|
||||
new Operator(new String(new char[]{0x99}), "B2C_sub", true),
|
||||
},{
|
||||
new Operator(2, new String(new char[]{0x89}), "B2C_add", 3),
|
||||
new Operator(2, new String(new char[]{0x99}), "B2C_sub", 3),
|
||||
new Operator(new String(new char[]{0x86}), "B2C_sqrt", true, 1),
|
||||
},{
|
||||
new Operator(new String(new char[]{0x10}), "B2C_lessOrEqualThan", false),
|
||||
new Operator(new String(new char[]{0x12}), "B2C_greaterOrEqualThan", false),
|
||||
new Operator("<", "B2C_lessThan", false),
|
||||
new Operator(">", "B2C_greaterThan", false),
|
||||
new Operator("=", "B2C_equalTo", false),
|
||||
new Operator(new String(new char[]{0x11}), "B2C_notEqualTo", false),
|
||||
},{
|
||||
new Operator(2, new String(new char[]{0x10}), "B2C_lessOrEqualThan", 4),
|
||||
new Operator(2, new String(new char[]{0x12}), "B2C_greaterOrEqualThan", 4),
|
||||
new Operator(2, "<", "B2C_lessThan", 4),
|
||||
new Operator(2, ">", "B2C_greaterThan", 4),
|
||||
new Operator(2, "=", "B2C_equalTo", 4),
|
||||
new Operator(2, new String(new char[]{0x11}), "B2C_notEqualTo", 4),
|
||||
new Operator(new String(new char[]{0x7F, 0xB0}), "B2C_and", false),
|
||||
},{
|
||||
new Operator(2, new String(new char[]{0x7F, 0xB0}), "B2C_and", 5),
|
||||
},{
|
||||
new Operator(2, new String(new char[]{0x7F, 0xB1}), "B2C_or", 6),
|
||||
new Operator(2, new String(new char[]{0x7F, 0xB4}), "B2C_xor", 6),
|
||||
new Operator(new String(new char[]{0x7F, 0xB1}), "B2C_or", false),
|
||||
new Operator(new String(new char[]{0x7F, 0xB4}), "B2C_xor", false),
|
||||
}};
|
||||
|
||||
public static void initOperators() {
|
||||
maxPrecedence = operators.length-1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,13 +9,19 @@ public class Parser {
|
|||
final static int WHOLE_INSTRUCTION = 1;
|
||||
final static int CONV_TO_BCD = 2;
|
||||
final static int CONV_TO_INT = 3;
|
||||
|
||||
|
||||
final static int BCD_BUFFER = 0;
|
||||
final static int STR_BUFFER = 1;
|
||||
final static int LIST_BUFFER = 2;
|
||||
final static int MAT_BUFFER = 3;
|
||||
final static String[] bufferVars = {"bcdBuffer", "strBuffer", "listBuffer", "matBuffer"};
|
||||
final static String[] bufferTypes = {"BCDvar", "Str", "List", "Mat"};
|
||||
static String tabs = "\t";
|
||||
|
||||
//Be sure to clear these variables between programs.
|
||||
static ArrayList<String> instructions = new ArrayList<String>();
|
||||
static int instructionNumber = 0;
|
||||
static int nbBuffers = 0;
|
||||
static int[] buffers = {0,0,0,0};
|
||||
|
||||
|
||||
public static String parse(String content) {
|
||||
|
@ -37,22 +43,8 @@ public class Parser {
|
|||
*/
|
||||
|
||||
public static String parse(String content, int option) {
|
||||
|
||||
String instruction = "";
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
if (content.charAt(i) >= 32 && content.charAt(i) < 127) {
|
||||
instruction += content.charAt(i) + " ";
|
||||
} else {
|
||||
String hex = Integer.toHexString(content.charAt(i));
|
||||
instruction += "0x" + hex + " ";
|
||||
if (hex.length() > 2) {
|
||||
error("Unhandled unicode character u+" + hex.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Parsing instruction: " + instruction);
|
||||
|
||||
|
||||
|
||||
System.out.println("Parsing instruction: " + printNonAscii(content));
|
||||
|
||||
if (content.equals("")) {
|
||||
return "";
|
||||
|
@ -69,43 +61,49 @@ public class Parser {
|
|||
matchResult = checkMatch(content, ":");
|
||||
if (matchResult >= 0) {
|
||||
instructions.add(instructionNumber, content.substring(matchResult+1));
|
||||
instructionNumber++;
|
||||
return parse(content.substring(0, matchResult), WHOLE_INSTRUCTION) + "\n" + tabs +
|
||||
parse(content.substring(matchResult+1), WHOLE_INSTRUCTION);
|
||||
}
|
||||
|
||||
if (content.startsWith("\"") && option == WHOLE_INSTRUCTION) {
|
||||
System.out.println("Hardcoded string detected, removing it...");
|
||||
return "";
|
||||
|
||||
if (startsWithStringFunction(content)) {
|
||||
if (option == WHOLE_INSTRUCTION) {
|
||||
error("B2C does not support standalone strings!");
|
||||
} else {
|
||||
return parseStr(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//The easy functions: those that always have their arguments after, AND that don't return anything. (exception of =>)
|
||||
//Functions like Int or Frac have their arguments after but return a value so they can be used in a calculation.
|
||||
//Those are listed in the alphabetical order of their opcodes.
|
||||
//So List (0x7F51) is above Lbl (0xE2) which is above If (0xF700). (again, exception of => which is after IfEnd)
|
||||
|
||||
//RanInt#(
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x87}))) {
|
||||
//So Fill (0x7F47) is above Lbl (0xE2) which is above If (0xF700). (again, exception of => which is after IfEnd)
|
||||
|
||||
//Fill(
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x47}))) {
|
||||
if (content.charAt(content.length()-1) == ')') {
|
||||
content = content.substring(0, content.length()-1);
|
||||
}
|
||||
Integer[] args = parseArgs(content);
|
||||
if (args.length != 1) {
|
||||
error("RanInt# method doesn't have 2 arguments!");
|
||||
error("Fill method doesn't have 2 arguments!");
|
||||
}
|
||||
return supportAns("B2C_ranInt(" + addBuffer() + ", " + parse(content.substring(2, args[0]), CONV_TO_BCD) + ","
|
||||
+ parse(content.substring(args[0]+1), CONV_TO_BCD) + ")", option);
|
||||
if (content.substring(args[0]+1).startsWith(new String(new char[]{0x7F,0x40}))) {
|
||||
return "B2C_fillMat(" + parse(content.substring(2, args[0]), CONV_TO_BCD) + ", "
|
||||
+ parse(content.substring(args[0]+1), CONV_TO_BCD) + ");";
|
||||
} else if (content.substring(args[0]+1).startsWith(new String(new char[]{0x7F,0x51}))) {
|
||||
return "B2C_fillList(" + parse(content.substring(2, args[0]), CONV_TO_BCD) + ", "
|
||||
+ parse(content.substring(args[0]+1), CONV_TO_BCD) + ");";
|
||||
} else {
|
||||
error("2nd argument of Fill isn't a Mat or a List!");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Getkey
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x8F}))) {
|
||||
if (content.length() > 2) {
|
||||
error("Instruction begins by GetKey but includes something else!");
|
||||
}
|
||||
|
||||
return supportAns("B2C_Getkey()", option);
|
||||
//unary plus = no purpose
|
||||
if (content.startsWith(new String(new char[]{0x89}))) {
|
||||
return parse(content.substring(1), option);
|
||||
}
|
||||
|
||||
//Lbl
|
||||
|
@ -333,6 +331,13 @@ public class Parser {
|
|||
return "ML_clear_vram();";
|
||||
}
|
||||
|
||||
//ClrMat
|
||||
if (content.startsWith(new String(new char[]{0xF9,0x1E}))) {
|
||||
if (content.length() != 3) {
|
||||
error("Invalid argument for ClrMat!");
|
||||
}
|
||||
return "B2C_clrMat(" + getMat(content.charAt(2)) + ");";
|
||||
}
|
||||
|
||||
|
||||
//End of starting functions. At this point the instruction is likely a mathematical operation, or a string,
|
||||
|
@ -385,7 +390,7 @@ public class Parser {
|
|||
} else if (content.substring(matchResult+1).matches("[A-Z]~[A-Z]")) {
|
||||
String assignment = parse(content.substring(0, matchResult), CONV_TO_BCD);
|
||||
incrementTabs();
|
||||
String result = "for (i = "+getAlphaVar(content.charAt(matchResult+1))+"; i <= "+getAlphaVar(content.charAt(matchResult+3))+"; i++) {\n"+tabs+"B2C_setAlphaVar(i, "+assignment+");\n";
|
||||
String result = "for (i = '"+content.charAt(matchResult+1)+"'; i <= '"+content.charAt(matchResult+3)+"'; i++) {\n"+tabs+"B2C_setAlphaVar(i, "+assignment+");\n";
|
||||
decrementTabs();
|
||||
return result + tabs + "}";
|
||||
|
||||
|
@ -416,7 +421,7 @@ public class Parser {
|
|||
if (check.length != 1) {
|
||||
error("Mat instruction does not have one comma!");
|
||||
}
|
||||
String result = "B2C_setMat(" + (content.charAt(matchResult+3)-'A') + ", " +
|
||||
String result = "B2C_setMatCase(" + getMat(content.charAt(matchResult+3)) + ", " +
|
||||
handleIntConversion(content.substring(matchResult+5, matchResult+5+check[0])) + ", " +
|
||||
handleIntConversion(content.substring(matchResult+5+check[0]+1, content.length()-1)) + ", " +
|
||||
parse(content.substring(0, matchResult), CONV_TO_BCD) + ");";
|
||||
|
@ -452,33 +457,54 @@ public class Parser {
|
|||
//at this point it is a mathematical operation
|
||||
//stock the level of the parentheses
|
||||
Integer[] parenthesesPos = parseBrackets(content);
|
||||
//System.out.println(Arrays.toString(parenthesesPos));
|
||||
|
||||
//Mat
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x40}))) {
|
||||
System.out.println("Parsing a matrix");
|
||||
//Before parsing, we must check if the entire instruction is a Mat instruction
|
||||
|
||||
//Before parsing, we must check if the Mat instruction does not include dimensions
|
||||
if (content.length() == 3) {
|
||||
String str = getMat(content.charAt(2));
|
||||
if (option == WHOLE_INSTRUCTION) {
|
||||
str = "B2C_setMat(" + getMat((char)0xC0) + ", " + str + ");";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
Integer[] check = parseBrackets(content);
|
||||
Integer[] arg = parseArgs(content.substring(check[0]+1, check[1]));
|
||||
if (check[1] == content.length()-1) {
|
||||
if (arg.length != 1) {
|
||||
error("matrix coordinates are fewer or more than two!");
|
||||
} else {
|
||||
return supportAns("&mat[" + (content.charAt(2)-'A') + "].data[mat[" + (content.charAt(2)-'A') + "].width*("
|
||||
return supportAns("&mat[" + getMat(content.charAt(2)) + "].data[mat[" + getMat(content.charAt(2)) + "].height*("
|
||||
/*+ handleIntConversion(parse(content.substring(check[0]+1, check[0]+1+arg[0]))) + ")+("
|
||||
+ handleIntConversion(parse(content.substring(check[0]+2+arg[0],content.length()-1))) + ")]", option);*/
|
||||
+ handleIntConversion(content.substring(check[0]+1, check[0]+1+arg[0])) + ")+("
|
||||
+ handleIntConversion(content.substring(check[0]+2+arg[0],content.length()-1)) + ")]", option);
|
||||
+ handleIntConversion(content.substring(check[0]+1, check[0]+1+arg[0])) + "-1)+("
|
||||
+ handleIntConversion(content.substring(check[0]+2+arg[0],content.length()-1)) + "-1)]", option);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Dim ; for now it cannot parse it automatically, need to wait for the getNextArg() function
|
||||
//TODO do getNextArg()
|
||||
//Dim
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x46}))) {
|
||||
|
||||
return "Dim " + parse(content.substring(2));
|
||||
//If it is Dim Mat
|
||||
if (content.substring(2).startsWith(new String(new char[]{0x7F, 0x40}))) {
|
||||
String result = "B2C_getDimMat(" + getMat(content.charAt(4)) + ")";
|
||||
if (option == WHOLE_INSTRUCTION)
|
||||
return "B2C_setList(LIST_ANS, " + result + ");";
|
||||
return result;
|
||||
|
||||
//If it is Dim List
|
||||
} else if (content.substring(2).startsWith(new String(new char[]{0x7F, 0x40}))) {
|
||||
return supportAns("&list["+getList(content.substring(2)) + "].nbElements", option);
|
||||
} else {
|
||||
error("Dim instruction is not followed by List or Mat!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -488,11 +514,18 @@ public class Parser {
|
|||
//Before parsing, we must check if the entire instruction is a List instruction
|
||||
Integer[] check = parseBrackets(content);
|
||||
|
||||
if (check.length == 0) {
|
||||
String result = getList(content.substring(2));
|
||||
if (option == WHOLE_INSTRUCTION)
|
||||
return "B2C_setList(LIST_ANS, " + result + ");";
|
||||
return result;
|
||||
}
|
||||
|
||||
if (check.length == 2 && check[1] == content.length()-1 || option == WHOLE_INSTRUCTION && check.length > 0) {
|
||||
if (check.length == 2 && check[1] == content.length()-1) {
|
||||
content = content.substring(0, content.length()-1);
|
||||
}
|
||||
return supportAns("list[" + handleIntConversion(parse(content.substring(2, check[0]))) + "].data["
|
||||
return supportAns("list[" + getList(content.substring(2, check[0])) + "].data["
|
||||
+ handleIntConversion(parse(content.substring(check[0]+1, content.length()))) + "]", option);
|
||||
}
|
||||
}
|
||||
|
@ -506,32 +539,44 @@ public class Parser {
|
|||
//test if the operator is not within parentheses
|
||||
boolean isInParentheses = false;
|
||||
for (int k = 0; k < parenthesesPos.length; k+=2) {
|
||||
if (j >= parenthesesPos[k] && j <= parenthesesPos[k+1]) {
|
||||
if (j-Operators.operators[h][i].getCasioChar().length() >= parenthesesPos[k] && j-Operators.operators[h][i].getCasioChar().length() <= parenthesesPos[k+1]) {
|
||||
isInParentheses = true;
|
||||
}
|
||||
}
|
||||
System.out.println("Parsing operator: " + Operators.operators[h][i].getAsciiFunction());
|
||||
//If the operator is at the beginning of the string, it isn't a binary operator
|
||||
if (!isInParentheses && (j != 0 && Operators.operators[h][i].getNbOperands() != 1)) {
|
||||
if (!isInParentheses && (j != Operators.operators[h][i].getCasioChar().length() || Operators.operators[h][i].getNbOperands() == 1)) {
|
||||
String str = "";
|
||||
|
||||
//System.out.println("Found the above operator");
|
||||
str += Operators.operators[h][i].getAsciiFunction() + "(";
|
||||
|
||||
//If it is a mathematical operation (pow, mult, div, add, sub, sqrt)
|
||||
if (str.startsWith("B2C_pow(") || str.startsWith("B2C_sqrt(") || str.startsWith("B2C_mult(") ||
|
||||
str.startsWith("B2C_div(") || str.startsWith("B2C_add(") || str.startsWith("B2C_sub(")) {
|
||||
str += addBuffer() + ", ";
|
||||
|
||||
//Check for special of unary plus operator (which does nothing)
|
||||
/*if (str.equals("B2C_unaryPlus(")) {
|
||||
return parse(content.substring(1), option);
|
||||
}*/
|
||||
|
||||
//If it is a mathematical operation
|
||||
if (Operators.operators[h][i].isMathematicalFunction()) {
|
||||
str += addBCDBuffer() + ", ";
|
||||
}
|
||||
if (!str.startsWith("B2C_not(")) {
|
||||
str += parse(content.substring(0, j-Operators.operators[h][i].getCasioChar().length()), CONV_TO_BCD) + ", " + parse(content.substring(j), CONV_TO_BCD) + ")";
|
||||
|
||||
if (Operators.operators[h][i].getNbOperands() != 1) {
|
||||
str += parse(content.substring(0, j-Operators.operators[h][i].getCasioChar().length()), CONV_TO_BCD) + ", " + parse(content.substring(j), CONV_TO_BCD);
|
||||
} else {
|
||||
str += "B2C_not(" + parse(content.substring(2)) + ")";
|
||||
//If it is an unary operator, check if we can convert them as a constant
|
||||
if (content.matches("[\\d\\x99\\x87\\.\\x86]+")) {
|
||||
//System.out.println("convert to const");
|
||||
Constants.add(content);
|
||||
return supportAns("&"+Constants.getVarNotation(content), option);
|
||||
} else {
|
||||
str += parse(content.substring(j), CONV_TO_BCD);
|
||||
}
|
||||
}
|
||||
if (option == WHOLE_INSTRUCTION) {
|
||||
str += ";";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
str += ")";
|
||||
return supportAns(str, option);
|
||||
}/* else {
|
||||
System.out.println("Operator was in parenthesis, ignoring it");
|
||||
}*/
|
||||
|
||||
}
|
||||
/*if (isMultibytePrefix(content.charAt(j))) {
|
||||
|
@ -541,19 +586,15 @@ public class Parser {
|
|||
}
|
||||
}
|
||||
|
||||
//this only occurs if the entire string is within parentheses, such as "(2+3)"
|
||||
if (parenthesesPos.length == 2 && parenthesesPos[0] == 0 && parenthesesPos[1] == content.length()-1) {
|
||||
return "(" + parse(content.substring(1, content.length()-1)) + ")";
|
||||
}
|
||||
|
||||
|
||||
//replace variables with their position in the var[] array; only do this if the string only contains the variable
|
||||
if (content.length() == 1 && !content.matches("^\\d")) {
|
||||
String result = "&var[" + getAlphaVar(content) + "]";
|
||||
return supportAns(result, option);
|
||||
if (content.matches("[A-Z\\xCD\\xCE\\xC0]")) {
|
||||
return handleAlphaVar(content, option);
|
||||
}
|
||||
|
||||
//Test if it is a number (note that it can be something like 2X, implicit multiplication)
|
||||
if (content.matches("^[\\d\\x99\\.](.+)?")) {
|
||||
if (content.matches("^[\\d\\x99\\x87\\.](.+)?")) {
|
||||
int testForImplicitMultiplication = -1;
|
||||
for (char i = '0'; i <= '9'; i++) {
|
||||
if (testForImplicitMultiplication < content.lastIndexOf(i)) {
|
||||
|
@ -561,8 +602,7 @@ public class Parser {
|
|||
}
|
||||
}
|
||||
if (testForImplicitMultiplication != content.length()-1) {
|
||||
return supportAns("B2C_mult(" + parse(content.substring(0, testForImplicitMultiplication+1), CONV_TO_BCD) +
|
||||
", " + parse(content.substring(testForImplicitMultiplication+1, content.length())) + ")", option);
|
||||
return parse(content.substring(0, testForImplicitMultiplication+1) + (char)0xA9 + content.substring(testForImplicitMultiplication+1, content.length()));
|
||||
}
|
||||
//At this point it is a number, add it to constants
|
||||
Constants.add(content);
|
||||
|
@ -584,9 +624,63 @@ public class Parser {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//At this point it is a calculation, check for calculations functions
|
||||
String result = "";
|
||||
//Any function that returns a BCD value must be here! (GetKey, RanInt...)
|
||||
//Don't forget to add the buffer!
|
||||
|
||||
//RanInt#(
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x87}))) {
|
||||
if (content.charAt(content.length()-1) == ')') {
|
||||
content = content.substring(0, content.length()-1);
|
||||
}
|
||||
Integer[] args = parseArgs(content);
|
||||
if (args.length != 1) {
|
||||
error("RanInt# method doesn't have 2 arguments!");
|
||||
}
|
||||
return supportAns("B2C_ranInt(" + addBCDBuffer() + ", " + parse(content.substring(2, args[0]), CONV_TO_BCD) + ","
|
||||
+ parse(content.substring(args[0]+1), CONV_TO_BCD) + ")", option);
|
||||
|
||||
}
|
||||
|
||||
//Getkey
|
||||
if (content.startsWith(new String(new char[]{0x7F,0x8F}))) {
|
||||
if (content.length() > 2) {
|
||||
error("Instruction begins by GetKey but includes something else!");
|
||||
}
|
||||
|
||||
return supportAns("B2C_getkey(" + addBCDBuffer() + ")", option);
|
||||
}
|
||||
|
||||
//Not
|
||||
if (content.startsWith(new String(new char[]{0x7F,0xB3}))) {
|
||||
|
||||
return supportAns("B2C_not(" + parse(content.substring(1, CONV_TO_BCD) + ")"), option);
|
||||
}
|
||||
|
||||
//Int
|
||||
if (content.startsWith(new String(new char[]{0xA6}))) {
|
||||
if (content.length() == 1) {
|
||||
error("Int instruction is standalone!");
|
||||
}
|
||||
return supportAns("B2C_int(" + addBCDBuffer() + ", " + parse(content.substring(1), CONV_TO_BCD) + ")", option);
|
||||
}
|
||||
|
||||
//Ran#
|
||||
if (content.startsWith(new String(new char[]{0xC1}))) {
|
||||
if (content.length() != 1) {
|
||||
error("Ran# instruction includes something else!");
|
||||
}
|
||||
return supportAns("B2C_rand(" + addBCDBuffer() + ")", option);
|
||||
}
|
||||
|
||||
//this only occurs if the entire string is within parentheses, such as "(2+3)"
|
||||
if (parenthesesPos.length == 2 && parenthesesPos[0] == 0 && parenthesesPos[1] == content.length()-1) {
|
||||
return "(" + parse(content.substring(1, content.length()-1)) + ")";
|
||||
}
|
||||
|
||||
|
||||
/*String result = "";
|
||||
if (content.matches("\\d+")) {
|
||||
//Parse numbers as a global variable (for example, 36 is replaced by a const BCDvar _36 which value is calculated at the beginning).
|
||||
if (!Constants.consts.contains(Integer.parseInt(content))) {
|
||||
|
@ -597,8 +691,8 @@ public class Parser {
|
|||
//Check if it is a lone variable
|
||||
} else if (content.matches("[A-Z\\xCD\\xCE\\xC0]")) {
|
||||
result += handleAlphaVar(content, option);
|
||||
return result;
|
||||
} /*else {
|
||||
return result;*/
|
||||
/*} else {
|
||||
result += "B2C_calcExp((unsigned char*)" + parseStr("\"" + content + "\"") + ")";
|
||||
return result;
|
||||
}*/
|
||||
|
@ -607,11 +701,12 @@ public class Parser {
|
|||
//At this point in the code, the method must have already returned
|
||||
//if it has detected at least one instruction it understands
|
||||
|
||||
error("function in the instruction above not recognized!");
|
||||
return "";
|
||||
error("function not recognized! " + printNonAscii(content));
|
||||
return "===COMPILATION ERROR===";
|
||||
}
|
||||
|
||||
/* This function is called to parse hardcoded lists (written like {1,2,3}).
|
||||
/**
|
||||
* This function is called to parse hardcoded lists (written like {1,2,3}).
|
||||
* At the moment the only functions calling this method are:
|
||||
* - Assignment operation on Dim Mat ({1,2}->Dim Mat M)
|
||||
* - Assignment operation on List ({1,2}->List 3)
|
||||
|
@ -654,8 +749,9 @@ public class Parser {
|
|||
return result.substring(0, result.length()-2) + ")";
|
||||
}
|
||||
|
||||
/* This method checks for the presence of the string match in the string content.
|
||||
* This can't be done with traditional methods because it must checks if the match
|
||||
/**
|
||||
* This method checks for the presence of the string match in the string content.
|
||||
* This can't be done with traditional methods because it must check if the match
|
||||
* string is in the content string AND not in a string.
|
||||
*
|
||||
* Returns -1 if the value doesn't exist, or the beginning of the first occurence of the match.
|
||||
|
@ -666,7 +762,6 @@ public class Parser {
|
|||
* because there is a '=>' but inside a string.
|
||||
*
|
||||
* checkMatch("A>B => Locate 1,1,C", "=>") will return 4.
|
||||
*
|
||||
*/
|
||||
|
||||
public static int checkMatch(String content, String match) {
|
||||
|
@ -741,7 +836,8 @@ public class Parser {
|
|||
return content;
|
||||
}
|
||||
|
||||
/* This method parses a string. It is designed to parse things like:
|
||||
/**
|
||||
* This method parses a string. It is designed to parse things like:
|
||||
* Str 1 + "test" + Str 2
|
||||
*
|
||||
* The main parse() method only calls this method in case of an argument that is always a string,
|
||||
|
@ -750,13 +846,56 @@ public class Parser {
|
|||
*/
|
||||
|
||||
public static String parseStr(String content) {
|
||||
System.out.println("Parsing string: "+content);
|
||||
if (content.startsWith("\"")/* || content.startsWith(new String(new char[]{0xF9, 0x3F}))*/) {
|
||||
if (content.startsWith("\"") && content.charAt(content.length()-1) != '"') {
|
||||
content += '"';
|
||||
System.out.println("Parsing string: "+printNonAscii(content));
|
||||
if (startsWithStringFunction(content)) {
|
||||
|
||||
//Parse operators
|
||||
//It is easy because the only operator is the '+'
|
||||
Integer[] parenthesesPos = parseBrackets(content);
|
||||
for (int i = content.length()-1; i >= 0; i--) {
|
||||
if (content.substring(0, i).endsWith(new String(new char[]{0x89}))) {
|
||||
//test if the operator is not within parentheses
|
||||
boolean isInParentheses = false;
|
||||
for (int k = 0; k < parenthesesPos.length; k+=2) {
|
||||
if (i-1 >= parenthesesPos[k] && i-1 <= parenthesesPos[k+1]) {
|
||||
isInParentheses = true;
|
||||
}
|
||||
}
|
||||
System.out.println("Parsing concatenation operator (+)");
|
||||
|
||||
if (!isInParentheses) {
|
||||
String str = "B2C_strcat(";
|
||||
str += parse(content.substring(0, i-1)) + ", " + parse(content.substring(i));
|
||||
str += ")";
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Note that standalone strings aren't supported, there is no Str Ans; therefore, no ';'!
|
||||
|
||||
//Plain strings
|
||||
if (content.startsWith("\"")) {
|
||||
if (content.charAt(content.length()-1) != '"') {
|
||||
content += '"';
|
||||
}
|
||||
content = replaceNonAscii(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
//All subsequent str functions have parenthesis, so check if there is the right number
|
||||
if (parenthesesPos.length != 2) {
|
||||
error("Str function does not have one level of parenthesis!");
|
||||
}
|
||||
|
||||
//Str function
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x3F}))) {
|
||||
return getStr(content.substring(2));
|
||||
}
|
||||
//StrRotate
|
||||
if (content.startsWith(new String(new char[]{0xF9, 0x3D}))) {
|
||||
return "B2C_strRotate(" + addStrBuffer() + parse(content.substring(2, parenthesesPos[0])) + ")";
|
||||
}
|
||||
content = replaceNonAscii(content);
|
||||
return content; //TODO parse Str function
|
||||
}
|
||||
return "B2C_convToStr(" + handleAlphaVar(content, NO_OPTION) + ")";
|
||||
}
|
||||
|
@ -784,7 +923,8 @@ public class Parser {
|
|||
return content;
|
||||
}
|
||||
|
||||
/* This method parses comma-separated arguments. It is used to parse any function
|
||||
/**
|
||||
* This method parses comma-separated arguments. It is used to parse any function
|
||||
* with those kind of arguments. It is needed because the arguments themselves may have
|
||||
* commas (example: Locate 1,Mat M[A,B],Str 1).
|
||||
*
|
||||
|
@ -824,13 +964,27 @@ public class Parser {
|
|||
* This function returns the index of each first-level opening and closing brackets/parentheses.
|
||||
* Example: the string "3*(4*(5+6))+(4*5)" will return {2, 10, 12, 16}.
|
||||
* It accounts for unmatched brackets at the end, so "2->Mat M[1,3" will return the same as "2->Mat M[1,3]".
|
||||
* When adding an opcode containing parenthesis, make sure to include it in this function.
|
||||
*/
|
||||
public static Integer[] parseBrackets(String content) {
|
||||
ArrayList<Integer> bracketsPos = new ArrayList<Integer>();
|
||||
int bracketsLevel = 0;
|
||||
boolean currentPositionIsString = false;
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
if ((content.charAt(i) == '(' || content.charAt(i) == '[' || content.charAt(i) == '{') && !currentPositionIsString) {
|
||||
if (!currentPositionIsString && (content.charAt(i) == '(' || content.charAt(i) == '[' || content.charAt(i) == '{' ||
|
||||
//Check for opcodes that contains parenthesis
|
||||
content.startsWith(new String(new char[]{0x7F, 0x87}), i) || //RanInt#(
|
||||
content.startsWith(new String(new char[]{0x7F, 0x47}), i) || //Fill(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x30}), i) || //StrJoin(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x34}), i) || //StrLeft(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x35}), i) || //StrRight(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x36}), i) || //StrMid(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x39}), i) || //StrUpr(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3A}), i) || //StrLwr(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3B}), i) || //StrInv(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3C}), i) || //StrShift(
|
||||
content.startsWith(new String(new char[]{0xF9, 0x3D}), i) //StrRotate(
|
||||
)) {
|
||||
bracketsLevel++;
|
||||
if (bracketsLevel == 1) {
|
||||
bracketsPos.add(i);
|
||||
|
@ -917,6 +1071,31 @@ public class Parser {
|
|||
return true;
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns true if the given string starts with a string function.
|
||||
* That means that Str, StrLwr, StrShift, '"', ... return true,
|
||||
* but not StrLen, StrCmp or StrSrc as they return BCDvars!
|
||||
*
|
||||
* The function must be the function alone, if there is something else then
|
||||
* it will return false.
|
||||
*/
|
||||
public static boolean startsWithStringFunction(String function) {
|
||||
if (function.startsWith(new String(new char[]{0xF9, 0x30})) || //StrJoin(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x34})) || //StrLeft(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x35})) || //StrRight(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x36})) || //StrMid(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x39})) || //StrUpr(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x3A})) || //StrLwr(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x3B})) || //StrInv(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x3C})) || //StrShift(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x3D})) || //StrRotate(
|
||||
function.startsWith(new String(new char[]{0xF9, 0x3F})) || //Str
|
||||
function.charAt(0) == '"'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String supportAns(String content, int option) {
|
||||
if (option == WHOLE_INSTRUCTION)
|
||||
|
@ -936,7 +1115,7 @@ public class Parser {
|
|||
public static String handleAlphaVar(String content, int option) {
|
||||
//Handle var such that var[char-'A'] gives the correct variable
|
||||
if (content.matches("[A-Z\\xCD\\xCE\\xC0]")) {
|
||||
String result = "&var[" + getAlphaVar(content) + "]";
|
||||
String result = getAlphaVar(content);
|
||||
return supportAns(result, option);
|
||||
}
|
||||
return parse(content, option);
|
||||
|
@ -951,30 +1130,86 @@ public class Parser {
|
|||
|
||||
public static String getAlphaVar(char var) {return getAlphaVar(""+var);}
|
||||
public static String getAlphaVar(String var) {
|
||||
String result = "VAR_";
|
||||
if (var.length() != 1) {
|
||||
error("Unknown var!");
|
||||
} else if (var.charAt(0) >= 'A' && var.charAt(0) <= 'Z') {
|
||||
return var;
|
||||
result += String.valueOf(var.charAt(0)-'A');
|
||||
} else if (var.charAt(0) == 0xCD) {
|
||||
return "RADIUS";
|
||||
result += "RADIUS";
|
||||
} else if (var.charAt(0) == 0xCE) {
|
||||
return "THETA";
|
||||
result += "THETA";
|
||||
} else if (var.charAt(0) == 0xC0) {
|
||||
return "ANS";
|
||||
result += "ANS";
|
||||
} else {
|
||||
error("Unknown var!");
|
||||
}
|
||||
error("Unknown var!");
|
||||
return "";
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String addBuffer() {
|
||||
String result = "&buffer" + nbBuffers;
|
||||
nbBuffers++;
|
||||
public static String getMat(char mat) {
|
||||
String result = "MAT_";
|
||||
if (mat >= 'A' && mat <= 'Z') {
|
||||
result += (mat-'A');
|
||||
} else if (mat == 0xC0) {
|
||||
result += "ANS";
|
||||
} else {
|
||||
error("Unknown mat "+mat+"!");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static String getList(String list) {
|
||||
if (list.length() == 1 && list.charAt(0) == 0xC0) {
|
||||
return "LIST_ANS";
|
||||
} else {
|
||||
return handleIntConversion(parse(list));
|
||||
}
|
||||
}
|
||||
public static String getStr(String str) {
|
||||
if (str.length() > 2) {
|
||||
error("Invalid str " + str + "!");
|
||||
}
|
||||
try {
|
||||
int strno = Integer.valueOf(str);
|
||||
if (strno < 1 || strno > 20) {
|
||||
error("Invalid str number " + strno + "!");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
error("Invalid str " + str + "!");
|
||||
}
|
||||
return "&str["+Integer.valueOf(str)+"]";
|
||||
|
||||
}
|
||||
|
||||
public static String addBCDBuffer() {return addBuffer(BCD_BUFFER);}
|
||||
public static String addStrBuffer() {return addBuffer(STR_BUFFER);}
|
||||
public static String addMatBuffer() {return addBuffer(MAT_BUFFER);}
|
||||
public static String addListBuffer() {return addBuffer(LIST_BUFFER);}
|
||||
|
||||
public static String addBuffer(int buffer) {
|
||||
String result = "&" + bufferVars[buffer] + buffers[buffer];
|
||||
buffers[buffer]++;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String printNonAscii(String content) {
|
||||
String result = "";
|
||||
for (int i = 0; i < content.length(); i++) {
|
||||
if (content.charAt(i) >= 32 && content.charAt(i) < 127) {
|
||||
result += content.charAt(i) + " ";
|
||||
} else {
|
||||
String hex = Integer.toHexString(content.charAt(i));
|
||||
result += "0x" + hex + " ";
|
||||
if (hex.length() > 2) {
|
||||
error("Unhandled unicode character u+" + hex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void error(String error) {
|
||||
System.out.println("\n===ERROR: "+error+"===\n");
|
||||
System.out.println("\nERROR: "+error+"\n");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,10 @@ public class Syscalls {
|
|||
static String syscallContent = "";
|
||||
static ArrayList<String> syscalls = new ArrayList<String>();
|
||||
static ArrayList<String> syscallIDs = new ArrayList<String>();
|
||||
|
||||
public static void addSyscall(String syscall, String syscallID) {
|
||||
syscalls.add(syscall);
|
||||
syscallIDs.add(syscallID);
|
||||
}
|
||||
|
||||
public static void createSyscallFile() {
|
||||
for (int i = 0; i < syscalls.size(); i++) {
|
||||
syscallContent += "\t.export\t_" + syscalls.get(i) + "\n";
|
||||
|
|
Loading…
Reference in New Issue