(function(arnoldc){
"use strict";
arnoldc.peg = (function() {
/*
* Generated by PEG.js 0.8.0.
*
* http://pegjs.majda.cz/
*/
function peg$subclass(child, parent) {
function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype;
child.prototype = new ctor();
}
function SyntaxError(message, expected, found, offset, line, column) {
this.message = message;
this.expected = expected;
this.found = found;
this.offset = offset;
this.line = line;
this.column = column;
this.name = "SyntaxError";
}
peg$subclass(SyntaxError, Error);
function parse(input) {
var options = arguments.length > 1 ? arguments[1] : {},
peg$FAILED = {},
peg$startRuleFunctions = { Root: peg$parseRoot },
peg$startRuleFunction = peg$parseRoot,
peg$c0 = [],
peg$c1 = "IT'S SHOWTIME",
peg$c2 = { type: "literal", value: "IT'S SHOWTIME", description: "\"IT'S SHOWTIME\"" },
peg$c3 = "YOU HAVE BEEN TERMINATED",
peg$c4 = { type: "literal", value: "YOU HAVE BEEN TERMINATED", description: "\"YOU HAVE BEEN TERMINATED\"" },
peg$c5 = "LISTEN TO ME VERY CAREFULLY",
peg$c6 = { type: "literal", value: "LISTEN TO ME VERY CAREFULLY", description: "\"LISTEN TO ME VERY CAREFULLY\"" },
peg$c7 = "HASTA LA VISTA, BABY",
peg$c8 = { type: "literal", value: "HASTA LA VISTA, BABY", description: "\"HASTA LA VISTA, BABY\"" },
peg$c9 = "HEY CHRISTMAS TREE",
peg$c10 = { type: "literal", value: "HEY CHRISTMAS TREE", description: "\"HEY CHRISTMAS TREE\"" },
peg$c11 = "YOU SET US UP",
peg$c12 = { type: "literal", value: "YOU SET US UP", description: "\"YOU SET US UP\"" },
peg$c13 = "GIVE YOU A LIFT",
peg$c14 = { type: "literal", value: "GIVE YOU A LIFT", description: "\"GIVE YOU A LIFT\"" },
peg$c15 = "GET UP",
peg$c16 = { type: "literal", value: "GET UP", description: "\"GET UP\"" },
peg$c17 = "GET DOWN",
peg$c18 = { type: "literal", value: "GET DOWN", description: "\"GET DOWN\"" },
peg$c19 = "YOU'RE FIRED",
peg$c20 = { type: "literal", value: "YOU'RE FIRED", description: "\"YOU'RE FIRED\"" },
peg$c21 = "HE HAD TO SPLIT",
peg$c22 = { type: "literal", value: "HE HAD TO SPLIT", description: "\"HE HAD TO SPLIT\"" },
peg$c23 = "TALK TO THE HAND",
peg$c24 = { type: "literal", value: "TALK TO THE HAND", description: "\"TALK TO THE HAND\"" },
peg$c25 = "I WANT TO ASK YOU A BUNCH OF QUESTIONS AND I WANT TO HAVE THEM ANSWERED IMMEDIATELY",
peg$c26 = { type: "literal", value: "I WANT TO ASK YOU A BUNCH OF QUESTIONS AND I WANT TO HAVE THEM ANSWERED IMMEDIATELY", description: "\"I WANT TO ASK YOU A BUNCH OF QUESTIONS AND I WANT TO HAVE THEM ANSWERED IMMEDIATELY\"" },
peg$c27 = "GET TO THE CHOPPER",
peg$c28 = { type: "literal", value: "GET TO THE CHOPPER", description: "\"GET TO THE CHOPPER\"" },
peg$c29 = "HERE IS MY INVITATION",
peg$c30 = { type: "literal", value: "HERE IS MY INVITATION", description: "\"HERE IS MY INVITATION\"" },
peg$c31 = "ENOUGH TALK",
peg$c32 = { type: "literal", value: "ENOUGH TALK", description: "\"ENOUGH TALK\"" },
peg$c33 = "I LIED",
peg$c34 = { type: "literal", value: "I LIED", description: "\"I LIED\"" },
peg$c35 = "NO PROBLEMO",
peg$c36 = { type: "literal", value: "NO PROBLEMO", description: "\"NO PROBLEMO\"" },
peg$c37 = "YOU ARE NOT YOU YOU ARE ME",
peg$c38 = { type: "literal", value: "YOU ARE NOT YOU YOU ARE ME", description: "\"YOU ARE NOT YOU YOU ARE ME\"" },
peg$c39 = "LET OFF SOME STEAM BENNET",
peg$c40 = { type: "literal", value: "LET OFF SOME STEAM BENNET", description: "\"LET OFF SOME STEAM BENNET\"" },
peg$c41 = "CONSIDER THAT A DIVORCE",
peg$c42 = { type: "literal", value: "CONSIDER THAT A DIVORCE", description: "\"CONSIDER THAT A DIVORCE\"" },
peg$c43 = "KNOCK KNOCK",
peg$c44 = { type: "literal", value: "KNOCK KNOCK", description: "\"KNOCK KNOCK\"" },
peg$c45 = "BECAUSE I'M GOING TO SAY PLEASE",
peg$c46 = { type: "literal", value: "BECAUSE I'M GOING TO SAY PLEASE", description: "\"BECAUSE I'M GOING TO SAY PLEASE\"" },
peg$c47 = "BULLSHIT",
peg$c48 = { type: "literal", value: "BULLSHIT", description: "\"BULLSHIT\"" },
peg$c49 = "YOU HAVE NO RESPECT FOR LOGIC",
peg$c50 = { type: "literal", value: "YOU HAVE NO RESPECT FOR LOGIC", description: "\"YOU HAVE NO RESPECT FOR LOGIC\"" },
peg$c51 = "STICK AROUND",
peg$c52 = { type: "literal", value: "STICK AROUND", description: "\"STICK AROUND\"" },
peg$c53 = "CHILL",
peg$c54 = { type: "literal", value: "CHILL", description: "\"CHILL\"" },
peg$c55 = "I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE",
peg$c56 = { type: "literal", value: "I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE", description: "\"I NEED YOUR CLOTHES YOUR BOOTS AND YOUR MOTORCYCLE\"" },
peg$c57 = "I'LL BE BACK",
peg$c58 = { type: "literal", value: "I'LL BE BACK", description: "\"I'LL BE BACK\"" },
peg$c59 = "DO IT NOW",
peg$c60 = { type: "literal", value: "DO IT NOW", description: "\"DO IT NOW\"" },
peg$c61 = "GIVE THESE PEOPLE AIR",
peg$c62 = { type: "literal", value: "GIVE THESE PEOPLE AIR", description: "\"GIVE THESE PEOPLE AIR\"" },
peg$c63 = "GET YOUR ASS TO MARS",
peg$c64 = { type: "literal", value: "GET YOUR ASS TO MARS", description: "\"GET YOUR ASS TO MARS\"" },
peg$c65 = "I LET HIM GO",
peg$c66 = { type: "literal", value: "I LET HIM GO", description: "\"I LET HIM GO\"" },
peg$c67 = peg$FAILED,
peg$c68 = null,
peg$c69 = function(method) {
return method
},
peg$c70 = function(statements) {
return {
methodType: "Main",
name: null,
methodParameters: [],
statements: statements
}
},
peg$c71 = function(variable) { return variable},
peg$c72 = function(name, methodParameters, returnsValue, statements) {
return {
methodType: returnsValue ? "NonVoid" : "Void",
name: name,
methodParameters: methodParameters,
statements: statements
}
},
peg$c73 = function(variableName, operand) {
return { statementType: "DeclareInt", variableName: variableName, operand: operand }
},
peg$c74 = function(operand) {
return { statementType: "Print", operand: operand }
},
peg$c75 = function(variableName, expression) {
return { statementType: "AssignVariable", variableName: variableName, expression: expression }
},
peg$c76 = function(statements) {
return statements
},
peg$c77 = function(conditionOperand, ifBranchStatements, elseBranchStatements) {
return {
statementType: "Condition",
conditionOperand: conditionOperand,
ifBranchStatements: ifBranchStatements,
elseBranchStatements: elseBranchStatements
}
},
peg$c78 = function(operand, statements) {
return { statementType: "While", operand: operand, statements: statements }
},
peg$c79 = function(variableName) { return variableName},
peg$c80 = function(operand) { return operand },
peg$c81 = function(assignVariableName, methodName, methodArguments) {
return { statementType: "CallMethod", assignVariableName: assignVariableName, methodName: methodName, methodArguments: methodArguments }
},
peg$c82 = function(assignVariableName) {
return { statementType: "CallReadMethod", assignVariableName: assignVariableName }
},
peg$c83 = function(operand) {
return { statementType: "Return", operand: operand }
},
peg$c84 = function(operand, operations) {
return { operand: operand, operations: operations }
},
peg$c85 = function(operand) { return { operationType: "arithmetic", operator: "+", operand: operand }},
peg$c86 = function(operand) { return { operationType: "arithmetic", operator: "-", operand: operand }},
peg$c87 = function(operand) { return { operationType: "arithmetic", operator: "*", operand: operand }},
peg$c88 = function(operand) { return { operationType: "arithmetic", operator: "/", operand: operand }},
peg$c89 = function(operand) { return { operationType: "arithmetic", operator: "%", operand: operand }},
peg$c90 = function(operand) { return { operationType: "logical", operator: "||", operand: operand } },
peg$c91 = function(operand) { return { operationType: "logical", operator: "&&", operand: operand } },
peg$c92 = function(operand) { return { operationType: "logical", operator: "==", operand: operand }},
peg$c93 = function(operand) { return { operationType: "logical", operator: ">", operand: operand }},
peg$c94 = function() {
return { operandType: "Identifier", name: text() }
},
peg$c95 = /^[A-Za-z]/,
peg$c96 = { type: "class", value: "[A-Za-z]", description: "[A-Za-z]" },
peg$c97 = /^[A-Za-z0-9]/,
peg$c98 = { type: "class", value: "[A-Za-z0-9]", description: "[A-Za-z0-9]" },
peg$c99 = function() {
return text()
},
peg$c100 = "-",
peg$c101 = { type: "literal", value: "-", description: "\"-\"" },
peg$c102 = /^[0-9]/,
peg$c103 = { type: "class", value: "[0-9]", description: "[0-9]" },
peg$c104 = function() {
return { operandType: "Literal", valueType: 'int', value: parseInt(text(), 10) }
},
peg$c105 = "@",
peg$c106 = { type: "literal", value: "@", description: "\"@\"" },
peg$c107 = function() { return { operandType: "Literal", valueType: 'bool', value: true } },
peg$c108 = function() { return { operandType: "Literal", valueType: 'bool', value: false } },
peg$c109 = function(value) {
return { operandType: "Literal", valueType: 'string', value: value }
},
peg$c110 = "\"",
peg$c111 = { type: "literal", value: "\"", description: "\"\\\"\"" },
peg$c112 = function(chars) { return chars.join("") },
peg$c113 = /^[^"\\]/,
peg$c114 = { type: "class", value: "[^\"\\\\]", description: "[^\"\\\\]" },
peg$c115 = /^[\r\t ]/,
peg$c116 = { type: "class", value: "[\\r\\t ]", description: "[\\r\\t ]" },
peg$c117 = /^[\n]/,
peg$c118 = { type: "class", value: "[\\n]", description: "[\\n]" },
peg$c119 = /^[\r\n\t ]/,
peg$c120 = { type: "class", value: "[\\r\\n\\t ]", description: "[\\r\\n\\t ]" },
peg$c121 = function() { return null },
peg$c122 = /^[ \t]/,
peg$c123 = { type: "class", value: "[ \\t]", description: "[ \\t]" },
peg$currPos = 0,
peg$reportedPos = 0,
peg$cachedPos = 0,
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
peg$maxFailPos = 0,
peg$maxFailExpected = [],
peg$silentFails = 0,
peg$result;
if ("startRule" in options) {
if (!(options.startRule in peg$startRuleFunctions)) {
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
}
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
}
function text() {
return input.substring(peg$reportedPos, peg$currPos);
}
function offset() {
return peg$reportedPos;
}
function line() {
return peg$computePosDetails(peg$reportedPos).line;
}
function column() {
return peg$computePosDetails(peg$reportedPos).column;
}
function expected(description) {
throw peg$buildException(
null,
[{ type: "other", description: description }],
peg$reportedPos
);
}
function error(message) {
throw peg$buildException(message, null, peg$reportedPos);
}
function peg$computePosDetails(pos) {
function advance(details, startPos, endPos) {
var p, ch;
for (p = startPos; p < endPos; p++) {
ch = input.charAt(p);
if (ch === "\n") {
if (!details.seenCR) { details.line++; }
details.column = 1;
details.seenCR = false;
} else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
details.line++;
details.column = 1;
details.seenCR = true;
} else {
details.column++;
details.seenCR = false;
}
}
}
if (peg$cachedPos !== pos) {
if (peg$cachedPos > pos) {
peg$cachedPos = 0;
peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
}
advance(peg$cachedPosDetails, peg$cachedPos, pos);
peg$cachedPos = pos;
}
return peg$cachedPosDetails;
}
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
peg$maxFailExpected = [];
}
peg$maxFailExpected.push(expected);
}
function peg$buildException(message, expected, pos) {
function cleanupExpected(expected) {
var i = 1;
expected.sort(function(a, b) {
if (a.description < b.description) {
return -1;
} else if (a.description > b.description) {
return 1;
} else {
return 0;
}
});
while (i < expected.length) {
if (expected[i - 1] === expected[i]) {
expected.splice(i, 1);
} else {
i++;
}
}
}
function buildMessage(expected, found) {
function stringEscape(s) {
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
return s
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\x08/g, '\\b')
.replace(/\t/g, '\\t')
.replace(/\n/g, '\\n')
.replace(/\f/g, '\\f')
.replace(/\r/g, '\\r')
.replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
var expectedDescs = new Array(expected.length),
expectedDesc, foundDesc, i;
for (i = 0; i < expected.length; i++) {
expectedDescs[i] = expected[i].description;
}
expectedDesc = expected.length > 1
? expectedDescs.slice(0, -1).join(", ")
+ " or "
+ expectedDescs[expected.length - 1]
: expectedDescs[0];
foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
return "Expected " + expectedDesc + " but " + foundDesc + " found.";
}
var posDetails = peg$computePosDetails(pos),
found = pos < input.length ? input.charAt(pos) : null;
if (expected !== null) {
cleanupExpected(expected);
}
return new SyntaxError(
message !== null ? message : buildMessage(expected, found),
expected,
found,
pos,
posDetails.line,
posDetails.column
);
}
function peg$parseRoot() {
var s0, s1;
s0 = [];
s1 = peg$parseAbstractMethod();
while (s1 !== peg$FAILED) {
s0.push(s1);
s1 = peg$parseAbstractMethod();
}
return s0;
}
function peg$parseBeginMain() {
var s0;
if (input.substr(peg$currPos, 13) === peg$c1) {
s0 = peg$c1;
peg$currPos += 13;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c2); }
}
return s0;
}
function peg$parseEndMain() {
var s0;
if (input.substr(peg$currPos, 24) === peg$c3) {
s0 = peg$c3;
peg$currPos += 24;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c4); }
}
return s0;
}
function peg$parseDeclareMethod() {
var s0;
if (input.substr(peg$currPos, 27) === peg$c5) {
s0 = peg$c5;
peg$currPos += 27;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c6); }
}
return s0;
}
function peg$parseEndMethodDeclaration() {
var s0;
if (input.substr(peg$currPos, 20) === peg$c7) {
s0 = peg$c7;
peg$currPos += 20;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c8); }
}
return s0;
}
function peg$parseDeclareInt() {
var s0;
if (input.substr(peg$currPos, 18) === peg$c9) {
s0 = peg$c9;
peg$currPos += 18;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c10); }
}
return s0;
}
function peg$parseSetInitialValue() {
var s0;
if (input.substr(peg$currPos, 13) === peg$c11) {
s0 = peg$c11;
peg$currPos += 13;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c12); }
}
return s0;
}
function peg$parsePlusOperator() {
var s0;
if (input.substr(peg$currPos, 15) === peg$c13) {
s0 = peg$c13;
peg$currPos += 15;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c14); }
}
return s0;
}
function peg$parsePlusOperatorDeprecated() {
var s0;
if (input.substr(peg$currPos, 6) === peg$c15) {
s0 = peg$c15;
peg$currPos += 6;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c16); }
}
return s0;
}
function peg$parseMinusOperator() {
var s0;
if (input.substr(peg$currPos, 8) === peg$c17) {
s0 = peg$c17;
peg$currPos += 8;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c18); }
}
return s0;
}
function peg$parseMultiplicationOperator() {
var s0;
if (input.substr(peg$currPos, 12) === peg$c19) {
s0 = peg$c19;
peg$currPos += 12;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c20); }
}
return s0;
}
function peg$parseDivisionOperator() {
var s0;
if (input.substr(peg$currPos, 15) === peg$c21) {
s0 = peg$c21;
peg$currPos += 15;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c22); }
}
return s0;
}
function peg$parsePrint() {
var s0;
if (input.substr(peg$currPos, 16) === peg$c23) {
s0 = peg$c23;
peg$currPos += 16;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c24); }
}
return s0;
}
function peg$parseRead() {
var s0;
if (input.substr(peg$currPos, 83) === peg$c25) {
s0 = peg$c25;
peg$currPos += 83;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c26); }
}
return s0;
}
function peg$parseAssignVariable() {
var s0;
if (input.substr(peg$currPos, 18) === peg$c27) {
s0 = peg$c27;
peg$currPos += 18;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c28); }
}
return s0;
}
function peg$parseSetValue() {
var s0;
if (input.substr(peg$currPos, 21) === peg$c29) {
s0 = peg$c29;
peg$currPos += 21;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
return s0;
}
function peg$parseEndAssignVariable() {
var s0;
if (input.substr(peg$currPos, 11) === peg$c31) {
s0 = peg$c31;
peg$currPos += 11;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c32); }
}
return s0;
}
function peg$parseFalse() {
var s0;
if (input.substr(peg$currPos, 6) === peg$c33) {
s0 = peg$c33;
peg$currPos += 6;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c34); }
}
return s0;
}
function peg$parseTrue() {
var s0;
if (input.substr(peg$currPos, 11) === peg$c35) {
s0 = peg$c35;
peg$currPos += 11;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
return s0;
}
function peg$parseEqualTo() {
var s0;
if (input.substr(peg$currPos, 26) === peg$c37) {
s0 = peg$c37;
peg$currPos += 26;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c38); }
}
return s0;
}
function peg$parseGreaterThan() {
var s0;
if (input.substr(peg$currPos, 25) === peg$c39) {
s0 = peg$c39;
peg$currPos += 25;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c40); }
}
return s0;
}
function peg$parseOr() {
var s0;
if (input.substr(peg$currPos, 23) === peg$c41) {
s0 = peg$c41;
peg$currPos += 23;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c42); }
}
return s0;
}
function peg$parseAnd() {
var s0;
if (input.substr(peg$currPos, 11) === peg$c43) {
s0 = peg$c43;
peg$currPos += 11;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c44); }
}
return s0;
}
function peg$parseIf() {
var s0;
if (input.substr(peg$currPos, 31) === peg$c45) {
s0 = peg$c45;
peg$currPos += 31;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c46); }
}
return s0;
}
function peg$parseElse() {
var s0;
if (input.substr(peg$currPos, 8) === peg$c47) {
s0 = peg$c47;
peg$currPos += 8;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c48); }
}
return s0;
}
function peg$parseEndIf() {
var s0;
if (input.substr(peg$currPos, 29) === peg$c49) {
s0 = peg$c49;
peg$currPos += 29;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c50); }
}
return s0;
}
function peg$parseWhile() {
var s0;
if (input.substr(peg$currPos, 12) === peg$c51) {
s0 = peg$c51;
peg$currPos += 12;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c52); }
}
return s0;
}
function peg$parseEndWhile() {
var s0;
if (input.substr(peg$currPos, 5) === peg$c53) {
s0 = peg$c53;
peg$currPos += 5;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c54); }
}
return s0;
}
function peg$parseMethodArguments() {
var s0;
if (input.substr(peg$currPos, 50) === peg$c55) {
s0 = peg$c55;
peg$currPos += 50;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c56); }
}
return s0;
}
function peg$parseReturn() {
var s0;
if (input.substr(peg$currPos, 12) === peg$c57) {
s0 = peg$c57;
peg$currPos += 12;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c58); }
}
return s0;
}
function peg$parseCallMethod() {
var s0;
if (input.substr(peg$currPos, 9) === peg$c59) {
s0 = peg$c59;
peg$currPos += 9;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c60); }
}
return s0;
}
function peg$parseNonVoidMethod() {
var s0;
if (input.substr(peg$currPos, 21) === peg$c61) {
s0 = peg$c61;
peg$currPos += 21;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c62); }
}
return s0;
}
function peg$parseAssignVariableFromMethodCall() {
var s0;
if (input.substr(peg$currPos, 20) === peg$c63) {
s0 = peg$c63;
peg$currPos += 20;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c64); }
}
return s0;
}
function peg$parseModulo() {
var s0;
if (input.substr(peg$currPos, 12) === peg$c65) {
s0 = peg$c65;
peg$currPos += 12;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c66); }
}
return s0;
}
function peg$parseAbstractMethod() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = peg$parseMainMethod();
if (s1 === peg$FAILED) {
s1 = peg$parseMethod();
}
if (s1 !== peg$FAILED) {
s2 = peg$parseEOL();
if (s2 === peg$FAILED) {
s2 = peg$c68;
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c69(s1);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseMainMethod() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parseBeginMain();
if (s1 !== peg$FAILED) {
s2 = peg$parseEOL();
if (s2 !== peg$FAILED) {
s3 = [];
s4 = peg$parseStatementBase();
while (s4 !== peg$FAILED) {
s3.push(s4);
s4 = peg$parseStatementBase();
}
if (s3 !== peg$FAILED) {
s4 = peg$parseEndMain();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c70(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseMethod() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;
s0 = peg$currPos;
s1 = peg$parseDeclareMethod();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseVariableName();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
s5 = [];
s6 = peg$currPos;
s7 = peg$parseMethodArguments();
if (s7 !== peg$FAILED) {
s8 = peg$parseWhiteSpace();
if (s8 !== peg$FAILED) {
s9 = peg$parseVariable();
if (s9 !== peg$FAILED) {
s10 = peg$parseEOL();
if (s10 !== peg$FAILED) {
peg$reportedPos = s6;
s7 = peg$c71(s9);
s6 = s7;
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
while (s6 !== peg$FAILED) {
s5.push(s6);
s6 = peg$currPos;
s7 = peg$parseMethodArguments();
if (s7 !== peg$FAILED) {
s8 = peg$parseWhiteSpace();
if (s8 !== peg$FAILED) {
s9 = peg$parseVariable();
if (s9 !== peg$FAILED) {
s10 = peg$parseEOL();
if (s10 !== peg$FAILED) {
peg$reportedPos = s6;
s7 = peg$c71(s9);
s6 = s7;
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
}
if (s5 !== peg$FAILED) {
s6 = peg$currPos;
s7 = peg$parseNonVoidMethod();
if (s7 !== peg$FAILED) {
s8 = peg$parseEOL();
if (s8 !== peg$FAILED) {
s7 = [s7, s8];
s6 = s7;
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
if (s6 === peg$FAILED) {
s6 = peg$c68;
}
if (s6 !== peg$FAILED) {
s7 = [];
s8 = peg$parseStatement();
while (s8 !== peg$FAILED) {
s7.push(s8);
s8 = peg$parseStatement();
}
if (s7 !== peg$FAILED) {
s8 = peg$parseEndMethodDeclaration();
if (s8 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c72(s3, s5, s6, s7);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseStatement() {
var s0;
s0 = peg$parseStatementBase();
if (s0 === peg$FAILED) {
s0 = peg$parseReturnStatement();
}
return s0;
}
function peg$parseStatementBase() {
var s0;
s0 = peg$parseDeclareIntStatement();
if (s0 === peg$FAILED) {
s0 = peg$parsePrintStatement();
if (s0 === peg$FAILED) {
s0 = peg$parseAssignVariableStatement();
if (s0 === peg$FAILED) {
s0 = peg$parseConditionStatement();
if (s0 === peg$FAILED) {
s0 = peg$parseWhileStatement();
if (s0 === peg$FAILED) {
s0 = peg$parseCallMethodStatement();
if (s0 === peg$FAILED) {
s0 = peg$parseCallReadMethodStatement();
}
}
}
}
}
}
return s0;
}
function peg$parseDeclareIntStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8;
s0 = peg$currPos;
s1 = peg$parseDeclareInt();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseVariableName();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
s5 = peg$parseSetInitialValue();
if (s5 !== peg$FAILED) {
s6 = peg$parseWhiteSpace();
if (s6 !== peg$FAILED) {
s7 = peg$parseOperand();
if (s7 !== peg$FAILED) {
s8 = peg$parseEOL();
if (s8 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c73(s3, s7);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parsePrintStatement() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parsePrint();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 === peg$FAILED) {
s3 = peg$parseString();
}
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c74(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseAssignVariableStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos;
s1 = peg$parseAssignVariable();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseVariableName();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
s5 = peg$parseExpression();
if (s5 !== peg$FAILED) {
s6 = peg$parseEndAssignVariable();
if (s6 !== peg$FAILED) {
s7 = peg$parseEOL();
if (s7 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c75(s3, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseConditionStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10;
s0 = peg$currPos;
s1 = peg$parseIf();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
s5 = [];
s6 = peg$parseStatement();
while (s6 !== peg$FAILED) {
s5.push(s6);
s6 = peg$parseStatement();
}
if (s5 !== peg$FAILED) {
s6 = peg$currPos;
s7 = peg$parseElse();
if (s7 !== peg$FAILED) {
s8 = peg$parseEOL();
if (s8 !== peg$FAILED) {
s9 = [];
s10 = peg$parseStatement();
while (s10 !== peg$FAILED) {
s9.push(s10);
s10 = peg$parseStatement();
}
if (s9 !== peg$FAILED) {
peg$reportedPos = s6;
s7 = peg$c76(s9);
s6 = s7;
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
if (s6 === peg$FAILED) {
s6 = peg$c68;
}
if (s6 !== peg$FAILED) {
s7 = peg$parseEndIf();
if (s7 !== peg$FAILED) {
s8 = peg$parseEOL();
if (s8 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c77(s3, s5, s6);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseWhileStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos;
s1 = peg$parseWhile();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
s5 = [];
s6 = peg$parseStatement();
while (s6 !== peg$FAILED) {
s5.push(s6);
s6 = peg$parseStatement();
}
if (s5 !== peg$FAILED) {
s6 = peg$parseEndWhile();
if (s6 !== peg$FAILED) {
s7 = peg$parseEOL();
if (s7 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c78(s3, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseCallMethodStatement() {
var s0, s1, s2, s3, s4, s5, s6, s7, s8;
s0 = peg$currPos;
s1 = peg$currPos;
s2 = peg$parseAssignVariableFromMethodCall();
if (s2 !== peg$FAILED) {
s3 = peg$parseWhiteSpace();
if (s3 !== peg$FAILED) {
s4 = peg$parseVariableName();
if (s4 !== peg$FAILED) {
s5 = peg$parseEOL();
if (s5 !== peg$FAILED) {
peg$reportedPos = s1;
s2 = peg$c79(s4);
s1 = s2;
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
if (s1 === peg$FAILED) {
s1 = peg$c68;
}
if (s1 !== peg$FAILED) {
s2 = peg$parseCallMethod();
if (s2 !== peg$FAILED) {
s3 = peg$parseWhiteSpace();
if (s3 !== peg$FAILED) {
s4 = peg$parseVariableName();
if (s4 !== peg$FAILED) {
s5 = [];
s6 = peg$currPos;
s7 = peg$parseWhiteSpace();
if (s7 !== peg$FAILED) {
s8 = peg$parseOperand();
if (s8 !== peg$FAILED) {
peg$reportedPos = s6;
s7 = peg$c80(s8);
s6 = s7;
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
while (s6 !== peg$FAILED) {
s5.push(s6);
s6 = peg$currPos;
s7 = peg$parseWhiteSpace();
if (s7 !== peg$FAILED) {
s8 = peg$parseOperand();
if (s8 !== peg$FAILED) {
peg$reportedPos = s6;
s7 = peg$c80(s8);
s6 = s7;
} else {
peg$currPos = s6;
s6 = peg$c67;
}
} else {
peg$currPos = s6;
s6 = peg$c67;
}
}
if (s5 !== peg$FAILED) {
s6 = peg$parseEOL();
if (s6 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c81(s1, s4, s5);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseCallReadMethodStatement() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$currPos;
s2 = peg$parseAssignVariableFromMethodCall();
if (s2 !== peg$FAILED) {
s3 = peg$parseWhiteSpace();
if (s3 !== peg$FAILED) {
s4 = peg$parseVariableName();
if (s4 !== peg$FAILED) {
s5 = peg$parseEOL();
if (s5 !== peg$FAILED) {
peg$reportedPos = s1;
s2 = peg$c79(s4);
s1 = s2;
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
if (s1 === peg$FAILED) {
s1 = peg$c68;
}
if (s1 !== peg$FAILED) {
s2 = peg$parseCallMethod();
if (s2 !== peg$FAILED) {
s3 = peg$parseEOL();
if (s3 !== peg$FAILED) {
s4 = peg$parseRead();
if (s4 !== peg$FAILED) {
s5 = peg$parseEOL();
if (s5 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c82(s1);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseReturnStatement() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parseReturn();
if (s1 !== peg$FAILED) {
s2 = peg$currPos;
s3 = peg$parseWhiteSpace();
if (s3 !== peg$FAILED) {
s4 = peg$parseOperand();
if (s4 !== peg$FAILED) {
peg$reportedPos = s2;
s3 = peg$c80(s4);
s2 = s3;
} else {
peg$currPos = s2;
s2 = peg$c67;
}
} else {
peg$currPos = s2;
s2 = peg$c67;
}
if (s2 === peg$FAILED) {
s2 = peg$c68;
}
if (s2 !== peg$FAILED) {
s3 = peg$parseEOL();
if (s3 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c83(s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseExpression() {
var s0, s1, s2, s3, s4, s5;
s0 = peg$currPos;
s1 = peg$currPos;
s2 = peg$parseSetValue();
if (s2 !== peg$FAILED) {
s3 = peg$parseWhiteSpace();
if (s3 !== peg$FAILED) {
s4 = peg$parseOperand();
if (s4 !== peg$FAILED) {
s5 = peg$parseEOL();
if (s5 !== peg$FAILED) {
peg$reportedPos = s1;
s2 = peg$c80(s4);
s1 = s2;
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
} else {
peg$currPos = s1;
s1 = peg$c67;
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseArithmeticOperation();
if (s3 === peg$FAILED) {
s3 = peg$parseLogicalOperation();
}
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseArithmeticOperation();
if (s3 === peg$FAILED) {
s3 = peg$parseLogicalOperation();
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c84(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseArithmeticOperation() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parsePlusOperator();
if (s1 === peg$FAILED) {
s1 = peg$parsePlusOperatorDeprecated();
}
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c85(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseMinusOperator();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c86(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseMultiplicationOperator();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c87(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseDivisionOperator();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c88(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseModulo();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c89(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
}
}
}
}
return s0;
}
function peg$parseLogicalOperation() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parseOr();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c90(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseAnd();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c91(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseEqualTo();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c92(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseGreaterThan();
if (s1 !== peg$FAILED) {
s2 = peg$parseWhiteSpace();
if (s2 !== peg$FAILED) {
s3 = peg$parseOperand();
if (s3 !== peg$FAILED) {
s4 = peg$parseEOL();
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c93(s3);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
}
}
}
return s0;
}
function peg$parseOperand() {
var s0;
s0 = peg$parseVariable();
if (s0 === peg$FAILED) {
s0 = peg$parseNumber();
if (s0 === peg$FAILED) {
s0 = peg$parseBoolean();
}
}
return s0;
}
function peg$parseVariable() {
var s0, s1;
s0 = peg$currPos;
s1 = peg$parseVariableName();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c94();
}
s0 = s1;
return s0;
}
function peg$parseVariableName() {
var s0, s1, s2, s3;
s0 = peg$currPos;
if (peg$c95.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c96); }
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c97.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c98); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c97.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c98); }
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c99();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseNumber() {
var s0, s1, s2, s3;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 45) {
s1 = peg$c100;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c101); }
}
if (s1 === peg$FAILED) {
s1 = peg$c68;
}
if (s1 !== peg$FAILED) {
s2 = [];
if (peg$c102.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c103); }
}
if (s3 !== peg$FAILED) {
while (s3 !== peg$FAILED) {
s2.push(s3);
if (peg$c102.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c103); }
}
}
} else {
s2 = peg$c67;
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c104();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseBoolean() {
var s0, s1, s2;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 64) {
s1 = peg$c105;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c106); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parseTrue();
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c107();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 64) {
s1 = peg$c105;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c106); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parseFalse();
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c108();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
}
return s0;
}
function peg$parseString() {
var s0, s1;
s0 = peg$currPos;
s1 = peg$parseStringValue();
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c109(s1);
}
s0 = s1;
return s0;
}
function peg$parseStringValue() {
var s0, s1, s2, s3;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
s1 = peg$c110;
peg$currPos++;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c111); }
}
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$parseChar();
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseChar();
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 34) {
s3 = peg$c110;
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c111); }
}
if (s3 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c112(s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseChar() {
var s0;
if (peg$c113.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c114); }
}
return s0;
}
function peg$parseEOL() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = [];
if (peg$c115.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c116); }
}
while (s2 !== peg$FAILED) {
s1.push(s2);
if (peg$c115.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c116); }
}
}
if (s1 !== peg$FAILED) {
if (peg$c117.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c118); }
}
if (s2 !== peg$FAILED) {
s3 = [];
if (peg$c119.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c120); }
}
while (s4 !== peg$FAILED) {
s3.push(s4);
if (peg$c119.test(input.charAt(peg$currPos))) {
s4 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c120); }
}
}
if (s3 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c121();
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
} else {
peg$currPos = s0;
s0 = peg$c67;
}
return s0;
}
function peg$parseWhiteSpace() {
var s0, s1, s2;
s0 = peg$currPos;
s1 = [];
if (peg$c122.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c123); }
}
while (s2 !== peg$FAILED) {
s1.push(s2);
if (peg$c122.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c123); }
}
}
if (s1 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c121();
}
s0 = s1;
return s0;
}
peg$result = peg$startRuleFunction();
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
return peg$result;
} else {
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
peg$fail({ type: "end", description: "end of input" });
}
throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
}
}
return {
SyntaxError: SyntaxError,
parse: parse
};
})();
})(arnoldc || (arnoldc = {}));
///
var arnoldc;
(function (arnoldc) {
/**
* Parses ArnoldC code.
* @param source - the ArnoldC code to parse
* @returns the resulting ParseTree
*/
function parse(source) {
var methods = arnoldc.peg.parse(source);
var parseTree = {
methods: methods
};
return parseTree;
}
arnoldc.parse = parse;
})(arnoldc || (arnoldc = {}));
///
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var arnoldc;
(function (arnoldc) {
/**
* Transpiles the source ArnoldC code to javascript code.
* @param source - the source ArnoldC code to be processed
* @returns the javascript code
*/
function transpileToJs(source) {
var parseTree = arnoldc.parse(source);
var context = createTranspileContext();
var sb = context.sb;
for (var i in parseTree.methods) {
if (i > 0) {
sb.appendLine();
}
var methodDeclaration = parseTree.methods[i];
appendMethodDeclarationJs(context, methodDeclaration);
}
if (!context.isMainMethodDeclared()) {
throw new TranspileError('Missing main method');
}
return sb.toString();
}
arnoldc.transpileToJs = transpileToJs;
/**
* Thrown when an error is detected during transpilation (after parsing is complete).
*/
var TranspileError = (function (_super) {
__extends(TranspileError, _super);
/**
* Constructs an error with the specified message.
* @param message - the error message
*/
function TranspileError(message) {
_super.call(this, message);
this.name = 'TranspileError';
this.message = 'WHAT THE FUCK DID I DO WRONG: ' + message;
}
return TranspileError;
})(Error);
arnoldc.TranspileError = TranspileError;
function createTranspileContext() {
var sb = createStringBuilder();
var methodNameMap = {};
var blockScopeStack = [];
var getCurrentBlockScope = function () {
if (blockScopeStack.length < 1) {
throw new TranspileError('No block scope is started');
}
return blockScopeStack[blockScopeStack.length - 1];
};
var currentMethodScope = null;
var context = {
sb: sb,
startMethod: function (methodName, hasReturnValue) {
if (currentMethodScope !== null) {
throw new TranspileError("A method (" + currentMethodScope.methodName + ") is already started.");
}
methodName = methodName || '';
if (methodNameMap[methodName]) {
throw new TranspileError("Method \"" + methodName + "\" is already defined.");
}
methodNameMap[methodName] = methodName;
currentMethodScope = createMethodScope(methodName, hasReturnValue);
blockScopeStack.push(createBlockScope());
sb.incrementIndentLevel();
},
endMethod: function () {
if (blockScopeStack.length !== 1) {
throw new TranspileError("Expected all block scopes to be ended, but there are " + (blockScopeStack.length - 1) + " still open.");
}
sb.decrementIndentLevel();
blockScopeStack.pop();
currentMethodScope = null;
},
isMainMethodDeclared: function () {
return !!methodNameMap[''];
},
startBlock: function () {
if (!currentMethodScope) {
throw new TranspileError("No method has not been started.");
}
blockScopeStack.push(createBlockScope());
sb.incrementIndentLevel();
},
endBlock: function () {
sb.decrementIndentLevel();
blockScopeStack.pop();
},
declareVariable: function (variableName) {
var currentBlockScope = getCurrentBlockScope();
currentBlockScope.declareVariable(variableName);
currentMethodScope.declareVariable(variableName);
},
referenceVariable: function (variableName) {
var isDeclared = false;
for (var _i = 0; _i < blockScopeStack.length; _i++) {
var blockScope = blockScopeStack[_i];
isDeclared = blockScope.isVariableDeclared(variableName);
if (isDeclared) {
break;
}
}
if (!isDeclared) {
throw new TranspileError("Variable \"" + variableName + "\" has not been declared.");
}
},
declareReturnStatement: function (operand) {
if (currentMethodScope.hasReturnValue === true && !operand) {
throw new TranspileError("Method \"" + currentMethodScope.methodName + "\" must return a value.");
}
if (currentMethodScope.hasReturnValue === false && !!operand) {
throw new TranspileError("Method \"" + currentMethodScope.methodName + "\" cannot return a value.");
}
},
};
return context;
}
function createBlockScope() {
var variableNameMap = {};
var blockScope = {
declareVariable: function (variableName) {
if (variableNameMap[variableName]) {
throw new TranspileError("Variable \"" + variableName + "\" is already defined");
}
variableNameMap[variableName] = variableName;
},
isVariableDeclared: function (variableName) {
return !!variableNameMap[variableName];
}
};
return blockScope;
}
function createMethodScope(methodName, hasReturnValue) {
var methodScope = createBlockScope();
methodScope.methodName = methodName;
methodScope.hasReturnValue = hasReturnValue;
return methodScope;
}
function createStringBuilder() {
var tokens = [];
var indentString = ' ';
var currentIndentLevel = 0;
var isLineIndented = false;
var append = function (value) {
if (!isLineIndented) {
for (var i = 0; i < currentIndentLevel; i++) {
tokens.push(indentString);
}
isLineIndented = true;
}
tokens.push(value);
};
var sb = {
append: append,
appendLine: function (value) {
if (value) {
append(value);
}
tokens.push('\n');
isLineIndented = false;
},
incrementIndentLevel: function () {
currentIndentLevel++;
isLineIndented = false;
},
decrementIndentLevel: function () {
if (currentIndentLevel > 0) {
currentIndentLevel--;
}
},
toString: function () {
return tokens.join('');
}
};
return sb;
}
;
function appendMethodDeclarationJs(context, methodDeclaration) {
var sb = context.sb;
var isMainMethod = (methodDeclaration.methodType === 'Main');
var hasReturnValue = !isMainMethod && methodDeclaration.methodType !== "Void";
var methodParameterNames = methodDeclaration.methodParameters.map(function (methodParameter) {
return methodParameter.name;
});
var escapedMethodParameterNames = methodParameterNames.map(function (parameterName) {
return escapeVariableName(parameterName);
});
if (isMainMethod) {
sb.append('(');
}
sb.append('function');
if (methodDeclaration.name) {
sb.append(' ');
sb.append(escapeMethodName(methodDeclaration.name));
}
sb.append('(');
sb.append(escapedMethodParameterNames.join(', '));
sb.appendLine(') {');
context.startMethod(methodDeclaration.name, hasReturnValue);
for (var _i = 0; _i < methodParameterNames.length; _i++) {
var methodParameterName = methodParameterNames[_i];
context.declareVariable(methodParameterName);
}
sb.appendLine('"use strict";');
for (var _a = 0, _b = methodDeclaration.statements; _a < _b.length; _a++) {
var statement = _b[_a];
appendStatementJs(context, statement);
}
context.endMethod();
sb.append('}');
if (isMainMethod) {
sb.append(')();');
}
sb.appendLine();
}
function appendStatementJs(context, statement) {
if (!statement)
return;
if (statement.statementType === "Condition") {
appendConditionStatementJs(context, statement);
}
else if (statement.statementType === "While") {
appendWhileStatementJs(context, statement);
}
else if (statement.statementType === "Print") {
appendPrintStatementJs(context, statement);
}
else if (statement.statementType === "DeclareInt") {
appendDeclareIntStatementJs(context, statement);
}
else if (statement.statementType === "AssignVariable") {
appendAssignVariableStatementJs(context, statement);
}
else if (statement.statementType === "CallMethod") {
appendCallMethodStatementJs(context, statement);
}
else if (statement.statementType === "CallReadMethod") {
appendCallReadMethodStatementJs(context, statement);
}
else if (statement.statementType === "Return") {
appendReturnStatementJs(context, statement);
}
else {
throw new TranspileError('Unrecognized statement type: ' + statement.statementType);
}
}
function appendConditionStatementJs(context, statement) {
var sb = context.sb;
sb.append('if (');
appendOperandJs(context, statement.conditionOperand);
sb.appendLine(') {');
context.startBlock();
for (var _i = 0, _a = statement.ifBranchStatements; _i < _a.length; _i++) {
var ifStatement = _a[_i];
appendStatementJs(context, ifStatement);
}
context.endBlock();
sb.append('}');
if (statement.elseBranchStatements && statement.elseBranchStatements.length > 0) {
sb.appendLine(' else {');
context.startBlock();
for (var _b = 0, _c = statement.elseBranchStatements; _b < _c.length; _b++) {
var elseStatement = _c[_b];
appendStatementJs(context, elseStatement);
}
context.endBlock();
sb.append('}');
}
sb.appendLine();
}
function appendWhileStatementJs(context, statement) {
var sb = context.sb;
sb.append('while (');
appendOperandJs(context, statement.operand);
sb.appendLine(') {');
context.startBlock();
for (var _i = 0, _a = statement.statements; _i < _a.length; _i++) {
var childStatement = _a[_i];
appendStatementJs(context, childStatement);
}
context.endBlock();
sb.appendLine('}');
}
function appendPrintStatementJs(context, statement) {
var sb = context.sb;
sb.append('console.log(');
appendOperandJs(context, statement.operand);
sb.appendLine(');');
}
function appendDeclareIntStatementJs(context, statement) {
var sb = context.sb;
context.declareVariable(statement.variableName);
sb.append('var ');
sb.append(escapeVariableName(statement.variableName));
if (statement.operand) {
sb.append(' = ');
appendOperandJs(context, statement.operand);
}
sb.appendLine(';');
}
function appendAssignVariableStatementJs(context, statement) {
var sb = context.sb;
context.referenceVariable(statement.variableName);
var variableName = escapeVariableName(statement.variableName);
// We need to go through each operation in the order given (all operators have equal precedence).
// This could be done all in one line with a lot of parentheses,
// but that makes it harder to do special handling for things like division by zero.
// So the current strategy is to do each operation on a separate line.
// We only need a temp variable if there is at least one operation that
// uses the original variable value (because then we can't change the
// original variable until all operations are complete).
var operations = statement.expression.operations;
var isTempVarNeeded = (operations.length > 0 &&
operations.filter(function (operation) {
return (operation.operand.operandType === "Identifier" &&
operation.operand.name === statement.variableName);
}).length > 0);
// The name of the temp variable doesn't really matter as long as it
// isn't a valid ArnoldC identifier (including what we escape variables to).
// And it doesn't matter if we end up declaring the temp variable more than once
// (javascript doesn't care so neither do we).
var tempVariableName = isTempVarNeeded ? "__temp" : variableName;
if (isTempVarNeeded) {
sb.append('var ');
}
sb.append(tempVariableName);
sb.append(' = ');
appendOperandJs(context, statement.expression.operand);
sb.appendLine(';');
for (var _i = 0, _a = statement.expression.operations; _i < _a.length; _i++) {
var operation = _a[_i];
var operator = operation.operator;
if (operator === '==') {
// Every ArnoldC variable should be a number, so it should
// be safe to use a strict equals.
operator = '===';
}
// Need special handling for division to detect divide by zero errors.
var isDivision = (operator === '/');
sb.append(tempVariableName);
sb.append(' = ');
sb.append('(');
sb.append(tempVariableName);
sb.append(' ');
sb.append(operator);
sb.append(' ');
appendOperandJs(context, operation.operand);
if (!isDivision) {
// Doing a bitwise and will convert the result to a signed 32-bit integer,
// This should get us the overflow/underflow behaviour that we need
// to match the real ArnoldC.
sb.appendLine(')|0;');
}
else {
sb.appendLine(');');
// Dividing by zero should result in Infinity (no error),
// But if we use a bitwise operation to change the result to a 32-bit signed int,
// then Infinity will be converted to zero.
// So we have to do the isFinite check before we do the int conversion.
sb.append('if (!isFinite(');
sb.append(tempVariableName);
sb.appendLine(')) {');
sb.incrementIndentLevel();
sb.appendLine('throw new Error("HERE\'S YOUR SUBZERO, NOW PLAIN ZERO");');
sb.decrementIndentLevel();
sb.appendLine('}');
sb.append(tempVariableName);
sb.append(' = ');
sb.append(tempVariableName);
sb.appendLine('|0;');
}
}
if (isTempVarNeeded) {
sb.append(variableName);
sb.append(' = ');
sb.append(tempVariableName);
sb.appendLine(';');
sb.append(tempVariableName);
sb.appendLine(' = undefined;');
}
}
function appendCallMethodStatementJs(context, statement) {
var sb = context.sb;
if (statement.assignVariableName) {
sb.append(escapeVariableName(statement.assignVariableName));
sb.append(' = ');
}
sb.append(escapeMethodName(statement.methodName));
sb.append('(');
for (var i = 0; i < statement.methodArguments.length; i++) {
if (i > 0) {
sb.append(', ');
}
var operand = statement.methodArguments[i];
appendOperandJs(context, operand);
}
sb.appendLine(');');
}
function appendCallReadMethodStatementJs(context, statement) {
var sb = context.sb;
context.referenceVariable(statement.assignVariableName);
var escapedVariableName = escapeVariableName(statement.assignVariableName);
sb.append(escapedVariableName);
sb.append(' = ');
sb.appendLine('prompt();');
// We need to match the behaviour of java.util.Scanner.nextInt().
// It stops parsing when it hits whitespace, but seems to ignore leading whitespace.
sb.append('if (/^\\s*[-+]?[0-9]+(\\s|$)/.test(');
sb.append(escapedVariableName);
sb.appendLine(') === false) {');
sb.incrementIndentLevel();
sb.append('throw new SyntaxError("input \\"" + ');
sb.append(escapedVariableName);
sb.appendLine(' + "\\" is not a number");');
sb.decrementIndentLevel();
sb.appendLine('}');
// The parseInt method will ignore any non-numeric suffix on the string,
// which means it will should ignore anything after non-leading whitespace.
// So that works out nicely for matching java.util.Scanner.
sb.append(escapedVariableName);
sb.append(' = parseInt(');
sb.append(escapedVariableName);
sb.appendLine(', 10);');
// We actually need to throw an error if the value is out of range,
// not just overflow/ underflow like we normally would.
sb.append('if (');
sb.append(escapedVariableName);
sb.append(' > 2147483647 || ');
sb.append(escapedVariableName);
sb.appendLine(' < -2147483648) {');
sb.incrementIndentLevel();
sb.appendLine('throw new RangeError("input is out of range for a 32-bit signed integer");');
sb.decrementIndentLevel();
sb.appendLine('}');
}
function appendReturnStatementJs(context, statement) {
var sb = context.sb;
context.declareReturnStatement(statement.operand);
sb.append('return');
if (statement.operand) {
sb.append(' ');
appendOperandJs(context, statement.operand);
}
sb.appendLine(';');
}
function appendOperandJs(context, operand) {
if (!operand)
return;
if (operand.operandType === "Literal") {
appendIdentifierLiteralJs(context, operand);
}
else if (operand.operandType === "Identifier") {
appendIdentifierOperandJs(context, operand);
}
else {
throw new TranspileError('Unrecognized operand type: ' + operand.operandType);
}
}
function appendIdentifierLiteralJs(context, operand) {
var sb = context.sb;
if (operand.valueType === 'int') {
var valueInt = operand.value;
if (valueInt > 32767 || valueInt < -32768) {
valueInt = convertNumberTo16BitSignedInteger(valueInt);
}
sb.append(valueInt.toString());
}
else if (operand.valueType === 'bool') {
sb.append(operand.value ? '1' : '0');
}
else if (operand.valueType === 'string') {
sb.append('"');
sb.append(escapeDoubleQuotedString(operand.value));
sb.append('"');
}
else {
throw new TranspileError('Unrecognized literal value type: ' + operand.valueType);
}
}
function appendIdentifierOperandJs(context, operand) {
context.referenceVariable(operand.name);
context.sb.append(escapeVariableName(operand.name));
}
function convertNumberTo16BitSignedInteger(value) {
// There's probably some fancier way to do this with bitwise operations,
// but this should at least get the right value? Hopefully...
if (value > 32767 || value < -32768) {
value = (modFixed((value + 32768), 65536) - 32768);
}
return value;
}
function modFixed(n, m) {
// Javascript mod can return a negative number, this avoids that problem.
return ((n % m) + m) % m;
}
;
function escapeDoubleQuotedString(str) {
if (!str)
return str;
// An ArnoldC string can contain anything except a double quote or a backslash.
// But some of that isn't valid in a javascript string,
// so we might have to do some escaping...
var escapedString = str
.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n');
return escapedString;
}
function escapeMethodName(methodName) {
// If we tried to use a javascript reserved word as a variable or method name,
// then we would get a runtime error. So we have to do something to avoid that.
var reservedWords = [
'break', 'default', 'function', 'return', 'var',
'case', 'delete', 'if', 'switch', 'void',
'catch', 'do', 'in', 'this', 'while',
'const', 'else', 'instanceof', 'throw', 'with',
'continue', 'finally', 'let', 'try', 'debugger',
'for', 'new', 'typeof'
];
if (reservedWords.indexOf(methodName) >= 0) {
// We can get around the reserved keyword restriction by using a unicode escape sequence
// for a character in the method name.
// This allows us to avoid changing the actual value of the method name
// in case some other library might try using the method.
var prefix = methodName.substr(0, methodName.length - 1);
var suffix = '\\u' + ('0000' + methodName.charCodeAt(methodName.length - 1).toString(16)).slice(-4);
methodName = prefix + suffix;
}
return methodName;
}
function escapeVariableName(variableName) {
// In ArnoldC, a method and a variable can have the same name.
// But in javascript, a variable with the same name as a method will hide that method.
// And the method could be declared either before or after the variable (or not at all),
// which makes it more complicated to deal with conditional escaping.
//
// So at least for now, we'll just escape all variable names with some prefix.
// The prefix can be any valid javascript variable name as long as it contains
// a character that isn't allowed in an ArnoldC variable name
// (like an underscore, dollar sign, or unicode escape sequence).
return '_' + variableName;
}
;
})(arnoldc || (arnoldc = {}));
///
var arnoldc;
(function (arnoldc) {
/**
* Transpiles the specified ArnoldC code to javascript and executes it.
* @param code - the ArnoldC code to execute
* @param options - any additional options to control how the code is executed
*/
function transpileToJsAndExecute(code, options) {
var js = arnoldc.transpileToJs(code);
return executeScript(js, options);
}
arnoldc.transpileToJsAndExecute = transpileToJsAndExecute;
function executeScript(js, options) {
if (!options)
options = {};
var consoleOverride = options.log ? { log: options.log } : console;
var promptOverride = options.prompt || prompt;
new Function('console', 'prompt', js)(consoleOverride, promptOverride);
}
})(arnoldc || (arnoldc = {}));