diff --git a/ArithmeticExpressionCompiler.zip b/ArithmeticExpressionCompiler.zip index 269c83d..2893b5a 100644 Binary files a/ArithmeticExpressionCompiler.zip and b/ArithmeticExpressionCompiler.zip differ diff --git a/compiler.html b/compiler.html index 068e298..0083b87 100644 --- a/compiler.html +++ b/compiler.html @@ -202,7 +202,7 @@


@@ -279,7 +279,7 @@

ArrayBuffer). Also, now there is a version that can be run in NodeJS, it can be downloaded here, maybe it comes useful to somebody.) @@ -712,7 +712,7 @@

}; ret.commentedLispExpression = function () { var commentedLispExpression = syntax == "gas" ? "#" : ";"; - if (syntaxHighlighting) + if (highlight) commentedLispExpression = '' + commentedLispExpression + @@ -721,12 +721,12 @@

'Pushing "' + this.toLisp() + '" to the FPU stack...'; for (var i = 0; i < lispExpression.length; i++) { var currentChar = lispExpression.charAt(i); - if (syntaxHighlighting) { + if (highlight) { if (currentChar == "&") currentChar = "&"; if (currentChar == "<") currentChar = "<"; if (currentChar == ">") currentChar = ">"; } - if (syntaxHighlighting) + if (highlight) commentedLispExpression += '' + currentChar + "<\/span>"; else commentedLispExpression += currentChar; @@ -1153,13 +1153,21 @@

} else if (!decimal && ret[i].charAt(j) == ".") decimal = 1; } } else if (ret[i].charAt(0) == '"' || ret[i].charAt(0) == "'") { - alerted = 1; - alert( - "Tokenizer error: The token " + - ret[i] + - " appears to be a string, which this program doesn't support." - ); - return ret; + if ( + ret[i].length == 3 && + ret[i].charAt(0) == ret[i].charAt(2) && + ret[i].charAt(0) == "'" + ) { + ret[i] = ret[i].charCodeAt(1).toString(); + } else { + alerted = 1; + alert( + "Tokenizer error: The token " + + ret[i] + + " appears to be a string, which this program doesn't support." + ); + return ret; + } } return ret; } diff --git a/control.js b/control.js index cf21292..adc0a74 100644 --- a/control.js +++ b/control.js @@ -15,6 +15,14 @@ function compileString(str) { if (syntax == "fasm") commentSign = ";"; else if (syntax == "gas") commentSign = "#"; else throw 'Driver error: Unrecognized syntax name "' + syntax + '"!'; + if (/^verboseMode\s*on/i.test(str)) { + verboseMode = true; + return; + } else if (/^verboseMode\s*off/i.test(str)) { + verboseMode = false; + return; + } else if (/^verboseMode\s*/i.test(str)) + throw 'Driver error: Please specify "VerboseMode" (for debugging the compiler) to be either "on" or "off"!'; if (/^AsmEnd/.test(str)) { asm(commentSign + str); asm(commentSign + "Inline assembly ended."); @@ -32,18 +40,31 @@ function compileString(str) { return; } asm(commentSign + str); - if (!str || str[0] == ";") return; + if (!str || str[0] == ";") { + if (verboseMode) + asm(commentSign + "The entire line is a comment, moving on..."); + return; + } var isString = false; for (var i = 0; i < str.length; i++) if (str[i] == '"' || str[i] == "'") isString = !isString; - else if (str[i] == ";") { + else if (str[i] == ";" && !isString) { //Obrisi komentar, ako se slucajno nesto kao '<=' ili ':=' nalazi u komentaru, da ne smeta parseru. str = str.substr(0, i); break; } - if (syntax == "gas") asm(".intel_syntax noprefix"); + if (syntax == "gas") { + if (verboseMode) + asm( + commentSign + + "We don't know which mode the assembler is in right now, so let's switch it to the intel_syntax mode." + ); + asm(".intel_syntax noprefix"); + } + if (verboseMode) asm(commentSign + "Initializing the FPU stack..."); asm("finit"); if (str.indexOf("<=") + 1) { + if (verboseMode) asm(commentSign + "Type of the directive is: constant."); var constantName = str.substr(0, str.indexOf("<=")); constantName = constantName.replace(/\s*$/, ""); var constantValue = str.substr(str.indexOf("<=") + "<=".length); @@ -55,10 +76,14 @@ function compileString(str) { } asm(constantName + "$:"); } else if (str.indexOf(":=") + 1) { + if (verboseMode) asm(commentSign + "Type of the directive is: assignment."); var variableName = str.substr(0, str.indexOf(":=")); variableName = variableName.replace(/\s*$/, ""); var arth = str.substr(str.indexOf(":=") + ":=".length); + if (verboseMode) asm(commentSign + "Calculating the rvalue..."); parseArth(tokenizeArth(arth)).compile(); + if (verboseMode) + asm(commentSign + 'Storing the top of the FPU stack into "edx".'); if (syntax == "fasm") asm("fstp dword [result]"); else asm("fstp dword ptr [result]"); if (syntax == "fasm") asm("mov edx, dword [result]"); @@ -72,54 +97,91 @@ function compileString(str) { indexOfBracket + 1, variableName.length - indexOfBracket - 2 ); + if (verboseMode) asm(commentSign + "Calculating the l-value..."); parseArth(tokenizeArth(subscript)).compile(); + if (verboseMode) + asm(commentSign + 'Moving the pointer from "st0" to "ebx".'); if (syntax == "fasm") asm("fistp dword [result]"); else asm("fistp dword ptr [result]"); if (syntax == "fasm") asm("mov ebx, dword [result]"); else asm("mov ebx, dword ptr [result]"); + if (verboseMode) + asm( + commentSign + + 'Storing the r-value (now in "edx") where "ebx" points to.' + ); if (syntax == "fasm") asm("mov dword [" + arrayName + "+4*ebx],edx"); else asm("mov dword ptr [" + arrayName + "+4*ebx],edx"); } else { + if (verboseMode) + asm( + commentSign + 'Storing the r-value (now in "edx") into the variable.' + ); if (syntax == "fasm") asm("mov dword [" + variableName + "],edx"); else asm("mov dword ptr [" + variableName + "],edx"); } } else if (/^If\s/.test(str)) { + if (verboseMode) + asm(commentSign + "Type of the directive is: if-statement."); var arth = str.substr("If ".length); + if (verboseMode) asm(commentSign + "Calculating the expression..."); parseArth(tokenizeArth(arth)).compile(); + if (verboseMode) + asm(commentSign + "Comparing the just-calculated expression with 0..."); if (syntax == "fasm") asm("fistp dword [result]"); else asm("fistp dword ptr [result]"); if (syntax == "fasm") asm("mov eax, dword [result]"); else asm("mov eax, dword ptr [result]"); asm("test eax,eax"); + if (verboseMode) + asm(commentSign + "Branching based on whether the expression is 0..."); var label1 = "ElseLabel" + Math.floor(Math.random() * 1000000); var label2 = "EndIfLabel" + Math.floor(Math.random() * 1000000); stack.push(label2); stack.push(label1); asm("jz " + label1); hasElse.push(false); - } else if (/^EndIf/.test(str)) + } else if (/^EndIf/.test(str)) { + if (verboseMode) + asm(commentSign + "Type of the directive is: EndIf-statement."); if (hasElse.pop()) asm(stack.pop() + ":"); else { asm(stack.pop() + ":"); asm(stack.pop() + ":"); } - else if (/^ElseIf\s/.test(str)) { + } else if (/^ElseIf\s/.test(str)) { + if (verboseMode) + asm(commentSign + "Type of the directive is: ElseIf-statement."); var labelOfElse = stack.pop(); var labelOfEndIf = stack.pop(); + if (verboseMode) + asm( + commentSign + "If the expression in the If-statement evaluates to 1..." + ); asm("jmp " + labelOfEndIf); + if (verboseMode) asm(commentSign + "If it evaluates to 0..."); asm(labelOfElse + ":"); var arth = str.substr("ElseIf ".length); + if (verboseMode) + asm( + commentSign + "Evaluating the expression after the ElseIf keyword..." + ); parseArth(tokenizeArth(arth)).compile(); + if (verboseMode) asm(commentSign + "Comparing that expression to 0..."); if (syntax == "fasm") asm("fistp dword [result]"); else asm("fistp dword ptr [result]"); if (syntax == "fasm") asm("mov eax, dword [result]"); else asm("mov eax, dword ptr [result]"); asm("test eax,eax"); + if (verboseMode) + asm(commentSign + "Branching based on whether it was 0..."); var newLabelOfElse = "ElseLabel" + Math.floor(Math.random() * 1000000); stack.push(labelOfEndIf); stack.push(newLabelOfElse); asm("jz " + newLabelOfElse); } else if (/^Else/.test(str)) { + if (verboseMode) + asm(commentSign + "Type of the directive: Else-statement."); var labelOfElse = stack.pop(); var labelOfEndIf = stack.pop(); asm("jmp " + labelOfEndIf); @@ -128,28 +190,57 @@ function compileString(str) { hasElse.pop(); hasElse.push(true); } else if (/^While\s/.test(str)) { + if (verboseMode) + asm(commentSign + "Type of the directive: beginning of the while-loop"); var arth = str.substr("While ".length); var label1 = "WhileLabel" + Math.floor(Math.random() * 1000000); stack.push(label1); + if (verboseMode) + asm( + commentSign + + "Marking where the evaluation of the expression begins (because it needs to be repeated once we come to the end of the loop)." + ); asm(label1 + ":"); + if (verboseMode) + asm(commentSign + 'Evaluating the expression after the "While" keyword'); parseArth(tokenizeArth(arth)).compile(); + if (verboseMode) asm(commentSign + "Comparing the expression to 0..."); var label2 = "EndWhileLabel" + Math.floor(Math.random() * 1000000); if (syntax == "fasm") asm("fistp dword [result]"); else asm("fistp dword ptr [result]"); if (syntax == "fasm") asm("mov eax, dword [result]"); else asm("mov eax, dword ptr [result]"); asm("test eax,eax"); + if (verboseMode) asm(commentSign + "Branching based on whether it is 0..."); asm("je " + label2); stack.push(label2); } else if (/^EndWhile/.test(str)) { + if (verboseMode) + asm(commentSign + "Type of the directive: end of the while-loop."); var endWhileLabel = stack.pop(); var whileLabel = stack.pop(); asm("jmp " + whileLabel); asm(endWhileLabel + ":"); } else { + if (verboseMode) + asm( + commentSign + + 'Type of the statement: unrecognized, passing it unchanged to "compiler.js".' + ); parseArth(tokenizeArth(str)).compile(); + if (verboseMode) + asm( + commentSign + 'Storing the just-computed expression into "result"...' + ); if (syntax == "fasm") asm("fstp dword [result]"); else asm("fstp dword ptr [result]"); } - if (syntax == "gas") asm(".att_syntax"); + if (syntax == "gas") { + if (verboseMode) + asm( + commentSign + + "We don't know what comes next, whichever program will control the assembler next will likely expect it to be in the att_syntax mode." + ); + asm(".att_syntax"); + } }