diff --git a/.idea/artifacts/TSVM_Executable.xml b/.idea/artifacts/TSVM_Executable.xml new file mode 100644 index 0000000..86a5498 --- /dev/null +++ b/.idea/artifacts/TSVM_Executable.xml @@ -0,0 +1,11 @@ + + + $PROJECT_DIR$/out/artifacts/TSVM_Executable + + + + + + + + \ No newline at end of file diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..32daa4c --- /dev/null +++ b/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2020 CuriousTorvald + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..2c70e1c --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Main-Class: net.torvald.tsvm.AppLoader +Class-Path: ./lib/GetCpuName.jar ./lib/TerranVirtualDisk.jar ./lib/annot + ations-13.0.jar ./lib/commons-codec-1.10.jar ./lib/commons-csv-1.2.jar + ./lib/gdx-backend-lwjgl-natives.jar ./lib/gdx-backend-lwjgl.jar ./lib/g + dx-natives.jar ./lib/gdx.jar ./lib/graal-sdk-20.3.0.jar ./lib/icu4j-67. + 1.jar ./lib/jnlp.jar ./lib/js-20.3.0.jar ./lib/js-scriptengine-20.3.0.j + ar ./lib/kotlin-reflect.jar ./lib/kotlin-stlib-1.4.0.jar ./lib/kotlin-s + tdlib-common-1.4.0.jar ./lib/kotlin-stdlib-jdk7.jar ./lib/kotlin-stdlib + -jdk8.jar ./lib/kotlin-stdlib.jar ./lib/kotlin-test.jar ./lib/kotlinx-c + oroutines-core-1.4.1.jar ./lib/regex-20.3.0.jar ./lib/truffle-api-20.3. + 0.jar + diff --git a/assets/bios/tbasdist.js b/assets/bios/tbasdist.js index f46446a..3ec97a1 100644 --- a/assets/bios/tbasdist.js +++ b/assets/bios/tbasdist.js @@ -1,3 +1,4 @@ +println("TSVM - Copyright 2020 CuriousTorvald"); var _BIOS = {}; @@ -22,13 +23,14 @@ if (r == 0){ r = com.getStatusCode(0); if (r == 0) { try { + println("Reading basic.js..."); let g=com.pullMessage(0); let execAppPrg = eval("var _appStub=function(exec_args){"+g+"};_appStub;"); // making 'exec_args' a app-level global execAppPrg(); return 0; } catch (e) { - printerrln("\n"+e.stack); + printerrln("\nApp Execution Error: "+(e.stack || e)); return 1; } } diff --git a/assets/disk0/tbas/basic.js b/assets/disk0/tbas/basic.js index 0f55498..1000749 100644 --- a/assets/disk0/tbas/basic.js +++ b/assets/disk0/tbas/basic.js @@ -2,9 +2,25 @@ // Version 1.0 Release Date 202?-??-?? /* -Copyright 2020 CuriousTorvald +Copyright (c) 2020 CuriousTorvald -Insert copyright notice here +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ if (exec_args !== undefined && exec_args[1] !== undefined && exec_args[1].startsWith("-?")) { diff --git a/assets/disk0/tbas/parser_wip.js b/assets/disk0/tbas/parser_wip.js deleted file mode 100644 index 8cdc65a..0000000 --- a/assets/disk0/tbas/parser_wip.js +++ /dev/null @@ -1,848 +0,0 @@ -class ParserError extends Error { - constructor(...args) { - super(...args); - Error.captureStackTrace(this, ParserError); - } -} -var DEFUNS_BUILD_DEFUNS = false; -let bF = {}; -bF.parserPrintdbg = any => serial.println(any); -bF.parserPrintdbg2 = function(icon, lnum, tokens, states, recDepth) { - let treeHead = String.fromCharCode(0x2502,32).repeat(recDepth); - bF.parserPrintdbg(`${icon}${lnum} ${treeHead}${tokens.join(' ')}`); - bF.parserPrintdbg(`${icon}${lnum} ${treeHead}${states.join(' ')}`); -} -bF.parserPrintdbgline = function(icon, msg, lnum, recDepth) { - let treeHead = String.fromCharCode(0x2502,32).repeat(recDepth); - bF.parserPrintdbg(`${icon}${lnum} ${treeHead}${msg}`); -} -let lang = {}; -lang.syntaxfehler = function(line, reason) { - return Error("Syntax error" + ((line !== undefined) ? (" in "+line) : "") + ((reason !== undefined) ? (": "+reason) : "")); -}; - -/** - * @return ARRAY of BasicAST - */ -bF._parseTokens = function(lnum, tokens, states) { - bF.parserPrintdbg2('Line ', lnum, tokens, states, 0); - - if (tokens.length !== states.length) throw lang.syntaxfehler(lnum); - if (tokens[0].toUpperCase() == "REM" && states[0] != "qot") return; - - /*************************************************************************/ - - let parenDepth = 0; - let parenStart = -1; - let parenEnd = -1; - let seps = []; - - // scan for parens and (:)s - for (let k = 0; k < tokens.length; k++) { - // increase paren depth and mark paren start position - if (tokens[k] == "(" && states[k] != "qot") { - parenDepth += 1; - if (parenStart == -1 && parenDepth == 1) parenStart = k; - } - // decrease paren depth - else if (tokens[k] == ")" && states[k] != "qot") { - if (parenEnd == -1 && parenDepth == 1) parenEnd = k; - parenDepth -= 1; - } - - if (parenDepth == 0 && tokens[k] == ":" && states[k] == "seq") - seps.push(k); - } - - let startPos = [0].concat(seps.map(k => k+1)); - let stmtPos = startPos.map((s,i) => {return{start:s, end:(seps[i] || tokens.length)}}); // use end of token position as separator position - - return stmtPos.map((x,i) => { - if (stmtPos.length > 1) - bF.parserPrintdbgline('Line ', 'Statement #'+(i+1), lnum, 0); - - // check for empty tokens - if (x.end - x.start <= 0) throw new ParserError("Malformed Line"); - - let tree = bF._parseStmt(lnum, - tokens.slice(x.start, x.end), - states.slice(x.start, x.end), - 1 - ); - - bF.parserPrintdbgline('Tree in ', '\n'+astToString(tree), lnum, 0); - - return tree; - }); -} - - -/** Parses following EBNF rule: -stmt = - "REM" , ? anything ? - | "IF" , expr_sans_asgn , "THEN" , stmt , ["ELSE" , stmt] - | "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , expr - | "ON" , expr_sans_asgn , ident , expr_sans_asgn , {"," , expr_sans_asgn} - | "(" , stmt , ")" - | expr ; (* if the statement is 'lit' and contains only one word, treat it as function_call e.g. NEXT for FOR loop *) - * @return: BasicAST - */ -bF._parseStmt = function(lnum, tokens, states, recDepth) { - bF.parserPrintdbg2('$', lnum, tokens, states, recDepth); - - /*************************************************************************/ - - // case for: single word (e.g. NEXT for FOR loop) - if (tokens.length == 1 && states.length == 1) { - bF.parserPrintdbgline('$', "Single Word Function Call", lnum, recDepth); - return bF._parseLit(lnum, tokens, states, recDepth + 1, true); - } - - /*************************************************************************/ - - let headTkn = tokens[0].toUpperCase(); - let headSta = states[0]; - - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - - /*************************************************************************/ - - // case for: "REM" , ? anything ? - if (headTkn == "REM" && headSta != "qot") return; - - /*************************************************************************/ - - let parenDepth = 0; - let parenStart = -1; - let parenEnd = -1; - let onGoPos = -1; - let sepsZero = []; - let sepsOne = []; - - // scan for parens that will be used for several rules - // also find nearest THEN and ELSE but also take parens into account - for (let k = 0; k < tokens.length; k++) { - // increase paren depth and mark paren start position - if (tokens[k] == "(" && states[k] != "qot") { - parenDepth += 1; - if (parenStart == -1 && parenDepth == 1) parenStart = k; - } - // decrease paren depth - else if (tokens[k] == ")" && states[k] != "qot") { - if (parenEnd == -1 && parenDepth == 1) parenEnd = k; - parenDepth -= 1; - } - - if (parenDepth == 0 && states[k] == "sep") - sepsZero.push(k); - if (parenDepth == 1 && states[k] == "sep") - sepsOne.push(k); - - if (parenDepth == 0) { - let tok = tokens[k].toUpperCase(); - if (-1 == onGoPos && ("GOTO" == tok || "GOSUB" == tok) && "lit" == states[k]) - onGoPos = k; - } - } - - // unmatched brackets, duh! - if (parenDepth != 0) throw lang.syntaxfehler(lnum, lang.unmatchedBrackets); - - /*************************************************************************/ - - // ## case for: - // "IF" , expr_sans_asgn , "THEN" , stmt , ["ELSE" , stmt] - try { - bF.parserPrintdbgline('$', "Trying IF Statement...", lnum, recDepth); - return bF._parseIfMode(lnum, tokens, states, recDepth + 1, false); - } - // if ParserError is raised, continue to apply other rules - catch (e) { - bF.parserPrintdbgline('$', 'It was NOT!', lnum, recDepth); - if (!(e instanceof ParserError)) throw e; - } - - /*************************************************************************/ - - // ## case for: - // | "DEFUN" , [ident] , "(" , [ident , {" , " , ident}] , ")" , "=" , expr - if ("DEFUN" == headTkn && "lit" == headSta && - parenStart == 2 && tokens[parenEnd + 1] == "=" && states[parenEnd + 1] == "op" - ) { - bF.parserPrintdbgline('$', 'DEFUN Stmt', lnum, recDepth); - - treeHead.astValue = "DEFUN"; - treeHead.astType = "function"; - - // parse function name - if (tokens[1] == "(") { - // anonymous function - treeHead.astLeaves[0] = new BasicAST(); - treeHead.astLeaves[0].astLnum = lnum; - treeHead.astLeaves[0].astType = "lit"; - } - else { - bF.parserPrintdbgline('$', 'DEFUN Stmt Function Name:', lnum, recDepth); - treeHead.astLeaves[0] = bF._parseIdent(lnum, [tokens[1]], [states[1]], recDepth + 1); - } - - // parse function arguments - bF.parserPrintdbgline('$', 'DEFUN Stmt Function Arguments -- ', lnum, recDepth); - let defunArgDeclSeps = sepsOne.filter((i) => i < parenEnd + 1).map(i => i-1).concat([parenEnd - 1]); - bF.parserPrintdbgline('$', 'DEFUN Stmt Function Arguments comma position: '+defunArgDeclSeps, lnum, recDepth); - - treeHead.astLeaves[0].astLeaves = defunArgDeclSeps.map(i=>bF._parseIdent(lnum, [tokens[i]], [states[i]], recDepth + 1)); - - // parse function body - let parseFunction = (DEFUNS_BUILD_DEFUNS) ? bF._parseStmt : bF._parseExpr; - treeHead.astLeaves[1] = parseFunction(lnum, - tokens.slice(parenEnd + 2, tokens.length), - states.slice(parenEnd + 2, states.length), - recDepth + 1 - ); - - return treeHead; - } - - /*************************************************************************/ - - // ## case for: - // | "ON" , if_equation , ident , if_equation , {"," , if_equation} - if ("ON" == headTkn && "lit" == headSta) { - bF.parserPrintdbgline('$', 'ON Stmt', lnum, recDepth); - - if (onGoPos == -1) throw ParserError("Malformed ON Statement"); - - treeHead.astValue = "ON"; - treeHead.astType = "function"; - - // parse testvalue - let testvalue = bF._parseExpr(lnum, - tokens.slice(1, onGoPos), - states.slice(1, onGoPos), - recDepth + 1, - true - ); - - // parse functionname - let functionname = bF._parseExpr(lnum, - [tokens[onGoPos]], - [states[onGoPos]], - recDepth + 1, - true - ); - - // parse arguments - // get list of comma but filter ones appear before GOTO/GOSUB - let onArgSeps = sepsZero.filter(i => (i > onGoPos)); - let onArgStartPos = [onGoPos + 1].concat(onArgSeps.map(k => k + 1)); - let onArgPos = onArgStartPos.map((s,i) => {return{start:s, end: (onArgSeps[i] || tokens.length)}}); // use end of token position as separator position - - // recursively parse expressions - treeHead.astLeaves = [testvalue, functionname].concat(onArgPos.map((x,i) => { - bF.parserPrintdbgline('$', 'ON GOTO/GOSUB Arguments #'+(i+1), lnum, recDepth); - - // check for empty tokens - if (x.end - x.start <= 0) throw new ParserError("Malformed ON arguments"); - - return bF._parseExpr(lnum, - tokens.slice(x.start, x.end), - states.slice(x.start, x.end), - recDepth + 1, - true - ); - })); - - return treeHead; - } - - /*************************************************************************/ - - // ## case for: - // | "(" , stmt , ")" - if (parenStart == 0 && parenEnd == tokens.length - 1) { - bF.parserPrintdbgline('$', '( Stmt )', lnum, recDepth); - return bF._parseStmt(lnum, - tokens.slice(parenStart + 1, parenEnd), - states.slice(parenStart + 1, parenEnd), - recDepth + 1 - ); - } - - /*************************************************************************/ - - // ## case for: - // | expr ; - try { - bF.parserPrintdbgline('$', 'Trying Expression Call...', lnum, recDepth); - return bF._parseExpr(lnum, tokens, states, recDepth + 1); - } - catch (e) { - bF.parserPrintdbgline('$', 'Error!', lnum, recDepth); - throw new ParserError("Statement cannot be parsed in "+lnum+": "+e.stack); - } - - /*************************************************************************/ - - throw new ParserError("Statement cannot be parsed in "+lnum); -} // END of STMT - - -/** Parses following EBNF rule: -expr = (* this basically blocks some funny attemps such as using DEFUN as anon function because everything is global in BASIC *) - lit - | "(" , expr , ")" - | "IF" , expr_sans_asgn , "THEN" , expr , ["ELSE" , expr] - | kywd , expr (* also deals with FOR statement; kywd = ? words that exists on the list of predefined function that are not operators ? ; *) - | function_call - | expr , op , expr - | op_uni , expr ; - - * @return: BasicAST - */ -bF._parseExpr = function(lnum, tokens, states, recDepth, ifMode) { - bF.parserPrintdbg2('E', lnum, tokens, states, recDepth); - - /*************************************************************************/ - - // ## special case for virtual dummy element (e.g. phantom element on "PRINT SPC(20);") - if (tokens[0] === undefined && states[0] === undefined) { - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - treeHead.astValue = undefined; - treeHead.astType = "null"; - - return treeHead; - } - - /*************************************************************************/ - - let headTkn = tokens[0].toUpperCase(); - let headSta = states[0]; - - /*************************************************************************/ - - // ## case for: - // lit - if (!bF._EquationIllegalTokens.includes(headTkn) && tokens.length == 1) { - bF.parserPrintdbgline('E', 'Literal Call', lnum, recDepth); - return bF._parseLit(lnum, tokens, states, recDepth + 1); - } - - /*************************************************************************/ - - // scan for operators with highest precedence, use rightmost one if multiple were found - let topmostOp; - let topmostOpPrc = 0; - let operatorPos = -1; - - // find and mark position of parentheses - // properly deal with the nested function calls - let parenDepth = 0; - let parenStart = -1; - let parenEnd = -1; - - // Scan for unmatched parens and mark off the right operator we must deal with - // every function_call need to re-scan because it is recursively called - for (let k = 0; k < tokens.length; k++) { - // increase paren depth and mark paren start position - if (tokens[k] == "(" && states[k] != "qot") { - parenDepth += 1; - if (parenStart == -1 && parenDepth == 1) parenStart = k; - } - // decrease paren depth - else if (tokens[k] == ")" && states[k] != "qot") { - if (parenEnd == -1 && parenDepth == 1) parenEnd = k; - parenDepth -= 1; - } - - // determine the right operator to deal with - if (parenDepth == 0) { - if (states[k] == "op" && bF.isSemanticLiteral(tokens[k-1], states[k-1]) && - ((bF._opPrc[tokens[k].toUpperCase()] > topmostOpPrc) || - (!bF._opRh[tokens[k].toUpperCase()] && bF._opPrc[tokens[k].toUpperCase()] == topmostOpPrc)) - ) { - topmostOp = tokens[k].toUpperCase(); - topmostOpPrc = bF._opPrc[tokens[k].toUpperCase()]; - operatorPos = k; - } - } - } - - // unmatched brackets, duh! - if (parenDepth != 0) throw lang.syntaxfehler(lnum, lang.unmatchedBrackets); - - /*************************************************************************/ - - // ## case for: - // | "(" , expr , ")" - if (parenStart == 0 && parenEnd == tokens.length - 1) { - bF.parserPrintdbgline('E', '( Expr )', lnum, recDepth); - - return bF._parseExpr(lnum, - tokens.slice(parenStart + 1, parenEnd), - states.slice(parenStart + 1, parenEnd), - recDepth + 1 - ); - } - - /*************************************************************************/ - - // ## case for: - // | "IF" , expr_sans_asgn , "THEN" , expr , ["ELSE" , expr] - try { - bF.parserPrintdbgline('E', "Trying IF Expression...", lnum, recDepth); - return bF._parseIfMode(lnum, tokens, states, recDepth + 1, false); - } - // if ParserError is raised, continue to apply other rules - catch (e) { - bF.parserPrintdbgline('E', 'It was NOT!', lnum, recDepth); - if (!(e instanceof ParserError)) throw e; - } - - /*************************************************************************/ - - // ## case for: - // | kywd , expr (* kywd = ? words that exists on the list of predefined function that are not operators ? ; *) - if (bStatus.builtin[headTkn] && headSta == "lit" && !bF._opPrc[headTkn] && - states[1] != "paren" - ) { - bF.parserPrintdbgline('E', 'Builtin Function Call w/o Paren', lnum, recDepth); - - return bF._parseFunctionCall(lnum, tokens, states, recDepth + 1); - } - - /*************************************************************************/ - - // ## case for: - // (* at this point, if OP is found in paren-level 0, skip function_call *) - // | function_call ; - if (topmostOp === undefined) { // don't remove this IF statement! - try { - bF.parserPrintdbgline('E', "Trying Function Call...", lnum, recDepth); - return bF._parseFunctionCall(lnum, tokens, states, recDepth + 1); - } - // if ParserError is raised, continue to apply other rules - catch (e) { - bF.parserPrintdbgline('E', 'It was NOT!', lnum, recDepth); - if (!(e instanceof ParserError)) throw e; - } - } - - /*************************************************************************/ - - // ## case for: - // | expr , op, expr - // | op_uni , expr - // if operator is found, split by the operator and recursively parse the LH and RH - if (topmostOp !== undefined) { - bF.parserPrintdbgline('E', 'Operators', lnum, recDepth); - - if (ifMode && topmostOp == "=") throw lang.syntaxfehler(lnum, "'=' used on IF, did you mean '=='?"); - if (ifMode && topmostOp == ":") throw lang.syntaxfehler(lnum, "':' used on IF"); - - - // this is the AST we're going to build up and return - // (other IF clauses don't use this) - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - treeHead.astValue = topmostOp; - treeHead.astType = "op"; - - // BINARY_OP? - if (operatorPos > 0) { - let subtknL = tokens.slice(0, operatorPos); - let substaL = states.slice(0, operatorPos); - let subtknR = tokens.slice(operatorPos + 1, tokens.length); - let substaR = states.slice(operatorPos + 1, tokens.length); - - treeHead.astLeaves[0] = bF._parseExpr(lnum, subtknL, substaL, recDepth + 1); - treeHead.astLeaves[1] = bF._parseExpr(lnum, subtknR, substaR, recDepth + 1); - } - else { - if (topmostOp === "-") treeHead.astValue = "UNARYMINUS" - else if (topmostOp === "+") treeHead.astValue = "UNARYPLUS" - else if (topmostOp === "NOT") treeHead.astValue = "UNARYLOGICNOT" - else if (topmostOp === "BNOT") treeHead.astValue = "UNARYBNOT" - else throw new ParserError(`Unknown unary op '${topmostOp}'`) - - treeHead.astLeaves[0] = bF._parseExpr(lnum, - tokens.slice(operatorPos + 1, tokens.length), - states.slice(operatorPos + 1, states.length), - recDepth + 1 - ); - } - - return treeHead; - } - - /*************************************************************************/ - - throw new ParserError("Expression cannot be parsed in "+lnum); -} // END of EXPR - - -/** Parses following EBNF rule: - "IF" , expr_sans_asgn , "THEN" , stmt , ["ELSE" , stmt] - | "IF" , expr_sans_asgn , "THEN" , expr , ["ELSE" , expr] - if exprMode is true, only the latter will be used; former otherwise - * @return: BasicAST - */ -bF._parseIfMode = function(lnum, tokens, states, recDepth, exprMode) { - bF.parserPrintdbg2('/', lnum, tokens, states, recDepth); - - /*************************************************************************/ - - let headTkn = tokens[0].toUpperCase(); - let headSta = states[0]; - - let parseFunction = (exprMode) ? bF._parseExpr : bF._parseStmt - - let thenPos = -1; - let elsePos = -1; - let parenDepth = 0; - let parenStart = -1; - let parenEnd = -1; - - // scan for parens that will be used for several rules - // also find nearest THEN and ELSE but also take parens into account - for (let k = 0; k < tokens.length; k++) { - // increase paren depth and mark paren start position - if (tokens[k] == "(" && states[k] != "qot") { - parenDepth += 1; - if (parenStart == -1 && parenDepth == 1) parenStart = k; - } - // decrease paren depth - else if (tokens[k] == ")" && states[k] != "qot") { - if (parenEnd == -1 && parenDepth == 1) parenEnd = k; - parenDepth -= 1; - } - - if (parenDepth == 0) { - if (-1 == thenPos && "THEN" == tokens[k].toUpperCase() && "lit" == states[k]) - thenPos = k; - else if (-1 == elsePos && "ELSE" == tokens[k].toUpperCase() && "lit" == states[k]) - elsePos = k; - } - } - - // unmatched brackets, duh! - if (parenDepth != 0) throw lang.syntaxfehler(lnum, lang.unmatchedBrackets); - - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - - // ## case for: - // "IF" , expr_sans_asgn , "THEN" , stmt , ["ELSE" , stmt] - if ("IF" == headTkn && "lit" == headSta) { - - // "THEN" not found, raise error! - if (thenPos == -1) throw lang.syntaxfehler(lnum, "IF without THEN"); - - treeHead.astValue = "IF"; - treeHead.astType = "function"; - - treeHead.astLeaves[0] = bF._parseExpr(lnum, - tokens.slice(1, thenPos), - states.slice(1, thenPos), - recDepth + 1, - true // if_equation mode - ); - treeHead.astLeaves[1] = parseFunction(lnum, - tokens.slice(thenPos + 1, (elsePos != -1) ? elsePos : tokens.length), - states.slice(thenPos + 1, (elsePos != -1) ? elsePos : tokens.length), - recDepth + 1 - ); - if (elsePos != -1) - treeHead.astLeaves[2] = parseFunction(lnum, - tokens.slice(elsePos + 1, tokens.length), - states.slice(elsePos + 1, tokens.length), - recDepth + 1 - ); - - return treeHead; - } - - throw new ParserError("not an IF "+(exprMode) ? "expression" : "statement"); -} // END of IF - - -/** Parses following EBNF rule: -function_call = - ident , "(" , [expr , {argsep , expr} , [argsep]] , ")" - | ident , expr , {argsep , expr} , [argsep] ; - * @return: BasicAST - */ -bF._parseFunctionCall = function(lnum, tokens, states, recDepth) { - bF.parserPrintdbg2(String.fromCharCode(0x192), lnum, tokens, states, recDepth); - - /*************************************************************************/ - - let parenDepth = 0; - let parenStart = -1; - let parenEnd = -1; - let _argsepsOnLevelZero = []; // argseps collected when parenDepth == 0 - let _argsepsOnLevelOne = []; // argseps collected when parenDepth == 1 - - // Scan for unmatched parens and mark off the right operator we must deal with - // every function_call need to re-scan because it is recursively called - for (let k = 0; k < tokens.length; k++) { - // increase paren depth and mark paren start position - if (tokens[k] == "(" && states[k] != "qot") { - parenDepth += 1; - if (parenStart == -1 && parenDepth == 1) parenStart = k; - } - // decrease paren depth - else if (tokens[k] == ")" && states[k] != "qot") { - if (parenEnd == -1 && parenDepth == 1) parenEnd = k; - parenDepth -= 1; - } - - if (parenDepth == 0 && states[k] == "sep") - _argsepsOnLevelZero.push(k); - if (parenDepth == 1 && states[k] == "sep") - _argsepsOnLevelOne.push(k); - } - - // unmatched brackets, duh! - if (parenDepth != 0) throw lang.syntaxfehler(lnum, lang.unmatchedBrackets); - let parenUsed = (parenStart == 1); - // && parenEnd == tokens.length - 1); - // if starting paren is found, just use it - // this prevents "RND(~~)*K" to be parsed as [RND, (~~)*K] - - /*************************************************************************/ - - // ## case for: - // ident , "(" , [expr , {argsep , expr} , [argsep]] , ")" - // | ident , expr , {argsep , expr} , [argsep] ; - bF.parserPrintdbgline(String.fromCharCode(0x192), `Function Call (parenUsed: ${parenUsed})`, lnum, recDepth); - - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - - // set function name and also check for syntax by deliberately parsing the word - treeHead.astValue = bF._parseIdent(lnum, [tokens[0]], [states[0]], recDepth + 1).astValue; // always UPPERCASE - - // 5 8 11 [end] - let argSeps = parenUsed ? _argsepsOnLevelOne : _argsepsOnLevelZero; // choose which "sep tray" to use - bF.parserPrintdbgline(String.fromCharCode(0x192), "argSeps = "+argSeps, lnum, recDepth); - // 1 6 9 12 - let argStartPos = [1 + (parenUsed)].concat(argSeps.map(k => k+1)); - bF.parserPrintdbgline(String.fromCharCode(0x192), "argStartPos = "+argStartPos, lnum, recDepth); - // [1,5) [6,8) [9,11) [12,end) - let argPos = argStartPos.map((s,i) => {return{start:s, end:(argSeps[i] || (parenUsed ? parenEnd : tokens.length) )}}); // use end of token position as separator position - bF.parserPrintdbgline(String.fromCharCode(0x192), "argPos = "+argPos.map(it=>`${it.start}/${it.end}`), lnum, recDepth); - - // check for trailing separator - - - // recursively parse function arguments - treeHead.astLeaves = argPos.map((x,i) => { - bF.parserPrintdbgline(String.fromCharCode(0x192), 'Function Arguments #'+(i+1), lnum, recDepth); - - // check for empty tokens - if (x.end - x.start < 0) throw new ParserError("not a function call because it's malformed"); - - return bF._parseExpr(lnum, - tokens.slice(x.start, x.end), - states.slice(x.start, x.end), - recDepth + 1 - )} - ); - treeHead.astType = "function"; - treeHead.astSeps = argSeps.map(i => tokens[i]); - bF.parserPrintdbgline(String.fromCharCode(0x192), "astSeps = "+treeHead.astSeps, lnum, recDepth); - - return treeHead; -} - - -bF._parseIdent = function(lnum, tokens, states, recDepth) { - bF.parserPrintdbg2('i', lnum, tokens, states, recDepth); - - if (!Array.isArray(tokens) && !Array.isArray(states)) throw new ParserError("Tokens and states are not array"); - if (tokens.length != 1 || states[0] != "lit") throw new ParserError(`illegal tokens '${tokens}' with states '${states}' in ${lnum}`); - - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - treeHead.astValue = tokens[0].toUpperCase(); - treeHead.astType = "lit"; - - return treeHead; -} -/** - * @return: BasicAST - */ -bF._parseLit = function(lnum, tokens, states, recDepth, functionMode) { - bF.parserPrintdbg2(String.fromCharCode(0xA2), lnum, tokens, states, recDepth); - - if (!Array.isArray(tokens) && !Array.isArray(states)) throw new ParserError("Tokens and states are not array"); - if (tokens.length != 1) throw new ParserError("parseLit 1"); - - let treeHead = new BasicAST(); - treeHead.astLnum = lnum; - treeHead.astValue = ("qot" == states[0]) ? tokens[0] : tokens[0].toUpperCase(); - treeHead.astType = ("qot" == states[0]) ? "string" : - ("num" == states[0]) ? "num" : - (functionMode) ? "function" : "lit"; - - return treeHead; -} - - -bF._EquationIllegalTokens = ["IF","THEN","ELSE","DEFUN","ON"]; -bF.isSemanticLiteral = function(token, state) { - return undefined == token || "]" == token || ")" == token || - "qot" == state || "num" == state || "bool" == state || "lit" == state; -} - - -/////// TEST///////// -let astToString = function(ast, depth) { - let l__ = String.fromCharCode(0x2502,32); - let recDepth = depth || 0; - if (ast === undefined || ast.astType === undefined) return ""; - var sb = ""; - var marker = ("lit" == ast.astType) ? "i" : - ("op" == ast.astType) ? String.fromCharCode(0xB1) : - ("string" == ast.astType) ? String.fromCharCode(0xB6) : - ("num" == ast.astType) ? String.fromCharCode(0xA2) : - ("array" == ast.astType) ? "[" : - ("defun_args" === ast.astType) ? String.fromCharCode(0x3B4) : String.fromCharCode(0x192); - sb += l__.repeat(recDepth) + marker+" Line "+ast.astLnum+" ("+ast.astType+")\n"; - sb += l__.repeat(recDepth+1) + "leaves: "+(ast.astLeaves.length)+"\n"; - sb += l__.repeat(recDepth+1) + "value: "+ast.astValue+" (type: "+typeof ast.astValue+")\n"; - for (var k = 0; k < ast.astLeaves.length; k++) { - sb += astToString(ast.astLeaves[k], recDepth + 1); - sb += l__.repeat(recDepth+1) + " " + ast.astSeps[k] + "\n"; - } - sb += l__.repeat(recDepth)+String.fromCharCode(0x2570)+String.fromCharCode(0x2500).repeat(13)+'\n'; - return sb; -} -let BasicAST = function() { - this.astLnum = 0; - this.astLeaves = []; - this.astSeps = []; - this.astValue = undefined; - this.astType = "null"; // lit, op, string, num, array, function, null, defun_args (! NOT usrdefun !) -} -bF._opPrc = { - // function call in itself has highest precedence - "^":1, - "*":2,"/":2,"\\":2, - "MOD":3, - "+":4,"-":4, - "NOT":5,"BNOT":5, - "<<":6,">>":6, - "<":7,">":7,"<=":7,"=<":7,">=":7,"=>":7, - "==":8,"<>":8,"><":8, - "MIN":10,"MAX":10, - "BAND":20, - "BXOR":21, - "BOR":22, - "AND":30, - "OR":31, - "TO":40, - "STEP":41, - "!":50,"~":51, // array CONS and PUSH - "#": 52, // array concat - "<~": 100, // curry operator - "~>": 101, // closure operator - "=":999, - "IN":1000 -}; -bF._opRh = {"^":1,"=":1,"!":1,"IN":1,"<~":1,"~>":1}; -let bStatus = {}; -bStatus.builtin = {}; -["PRINT","NEXT","SPC","CHR","ROUND","SQR","RND","GOTO","GOSUB","DEFUN","FOR","MAP"].forEach(w=>{ bStatus.builtin[w] = 1 }); -let lnum = 10; - -// if s<2 then (nop1) else (if s < 9999 then nop2 else nop3) -let tokens1 = ["if","s","<","2","then","(","nop1",")","else","(","if","s","<","9999","then","nop2","else","nop3",")"]; -let states1 = ["lit","lit","op","num","lit","paren","lit","paren","lit","paren","lit","lit","op","num","lit","lit","lit","lit","paren"]; - -// DEFUN HYPOT(X,Y) = SQR(X*X+Y*Y) -let tokens2 = ["defun","HYPOT","(","X",",","Y",")","=","SQR","(","X","*","X","+","Y","*","Y",")"]; -let states2 = ["lit","lit","paren","lit","sep","lit","paren","op","lit","paren","lit","op","lit","op","lit","op","lit","paren"]; - -// DEFUN SINC(X) = SIN(X) / X -let tokens3 = ["DEFUN","SINC","(","X",")","=","SIN","(","X",")","/","X"]; -let states3 = ["lit","lit","paren","lit","paren","op","lit","paren","lit","paren","op","lit"]; - -// PRINT(IF S<2 THEN "111" ELSE IF S<3 THEN "222" ELSE "333") -let tokens4 = ["PRINT","(","IF","S","<","2","THEN","111","ELSE","IF","S","<","3","THEN","222","ELSE","333",")"]; -let states4 = ["lit","paren","lit","lit","op","lit","lit","qot","lit","lit","lit","op","lit","lit","qot","lit","qot","paren"]; - -// ON 6*SQR(X-3) GOTO X+1, X+2, X+3 -let tokens5 = ["ON","6","*","SQR","(","X","-","3",")","GOTO","X","+","1",",","X","+","2",",","X","+","3"]; -let states5 = ["lit","num","op","lit","paren","lit","op","num","paren","lit","lit","op","num","sep","lit","op","num","sep","lit","op","num"]; - -// FOR K=10 TO 1 STEP -1 -let tokens6 = ["FOR","K","=","10","TO","1","STEP","-","1"]; -let states6 = ["lit","lit","op","num","op","num","op","op","num"]; - -// print(chr(47+round(rnd(1))*45);) -let tokens7 = ["PRINT","(","CHR","(","47","+","ROUND","(","RND","(","1",")",")","*","45",")",";",")"]; -let states7 = ["lit","paren","lit","paren","num","op","lit","paren","lit","paren","num","paren","paren","op","num","paren","sep","paren"]; - -// PRINT 4 - 5 * 9 -let tokens8 = ["PRINT","4","-","5","*","9"]; -let states8 = ["lit","num","op","num","op","num"]; - -// NEXT -let tokens9 = ["NEXT"]; -let states9 = ["lit"]; - -// PRINT -3 -let tokens10 = ["PRINT","-","3"]; -let states10 = ["lit","op","num"]; - -// PRINT SPC(20-I); -let tokens11 = ["PRINT","SPC","(","20","-","I",")",";"]; -let states11 = ["lit","lit","paren","num","op","lit","paren","sep"]; - -// DEFUN FAC(N)=IF N==0 THEN 1 ELSE N*FAC(N-1) -let tokens12 = ["DEFUN","FAC","(","N",")","=","IF","N","==","0","THEN","1","ELSE","N","*","FAC","(","N","-","1",")"]; -let states12 = ["lit","lit","paren","lit","paren","op","lit","lit","op","num","lit","num","lit","lit","op","lit","paren","lit","op","num","paren"]; - -// K = MAP FAC , 1 TO 10 -let tokens13 = ["K","=","MAP","FAC",",","1","TO","10"]; -let states13 = ["lit","op","lit","lit","sep","num","op","num"]; - -// DEFUN FIB(N)=IF N==0 THEN 0 ELSE IF N==1 THEN 1 ELSE FIB(N-1)+FIB(N-2) -let tokens14 = ["DEFUN","FIB","(","N",")","=","IF","N","==","0","THEN","0", - "ELSE","IF","N","==","1","THEN","1", - "ELSE","FIB","(","N","-","1",")","+","FIB","(","N","-","2",")"]; -let states14 = ["lit","lit","paren","lit","paren","op","lit","lit","op","num","lit","num", - "lit","lit","lit","op","num","lit","num", - "lit","lit","paren","lit","op","num","paren","op","lit","paren","lit","op","num","paren"]; - -// PRINT(MAP FIB, 1 TO 10) is not broken, it's obvious syntax error -// use "PRINT MAP(FIB, 1 TO 10)" instead -let tokens15 = ["PRINT","MAP","(","FIB",",","1","TO","10",")"]; -let states15 = ["lit","lit","paren","lit","sep","num","op","num","paren"]; - -// DEFUN KA(X)=IF X>2 THEN DO(PRINT(HAI);PRINT(X)) ELSE DO(PRINT(BYE);PRINT(X)) -let tokens16 = ["DEFUN","KA","(","X",")","=","IF","X",">","2","THEN","DO","(","PRINT","(","HAI",")",";","PRINT","(","X",")",")","ELSE","DO","(","PRINT","(","BYE",")",";","PRINT","(","X",")",")"]; -let states16 = ["lit","lit","paren","lit","paren","op","lit","lit","op","num","lit","lit","paren","lit","paren","qot","paren","sep","lit","paren","lit","paren","paren","lit","lit","paren","lit","paren","qot","paren","sep","lit","paren","lit","paren","paren"]; - -// FILTER(FN<~HEAD XS, TAIL XS) -let tokens17 = ["FILTER","(","FN","<~","HEAD","XS",",","TAIL","XS",")"]; -let states17 = ["lit","paren","lit","op","lit","lit","sep","lit","lit","paren"]; - -try { - let trees = bF._parseTokens(lnum, - tokens17, - states17 - ); - trees.forEach((t,i) => { - serial.println("\nParsed Statement #"+(i+1)); - serial.println(astToString(t)); - }); -} -catch (e) { - serial.printerr(e); - serial.printerr(e.stack || "stack trace undefined"); -} diff --git a/lib/AppleJavaExtensions-1.4.jar.gz b/lib/AppleJavaExtensions-1.4.jar.gz deleted file mode 100644 index a4dec1b..0000000 --- a/lib/AppleJavaExtensions-1.4.jar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a33c7cfa851124610d83ffc30dc2495c8549c2a65a4cac9a30a152d7adb6b70 -size 8607 diff --git a/lib/Concentus-1.0-SNAPSHOT.jar b/lib/Concentus-1.0-SNAPSHOT.jar deleted file mode 100644 index 30cbf5b..0000000 Binary files a/lib/Concentus-1.0-SNAPSHOT.jar and /dev/null differ diff --git a/lib/TerrarumSansBitmap.jar b/lib/TerrarumSansBitmap.jar deleted file mode 100644 index 15b7e1f..0000000 Binary files a/lib/TerrarumSansBitmap.jar and /dev/null differ diff --git a/lib/Terrarum_Joise.jar b/lib/Terrarum_Joise.jar deleted file mode 100644 index ecef95b..0000000 Binary files a/lib/Terrarum_Joise.jar and /dev/null differ diff --git a/lib/gdx-backend-lwjgl3.jar.gz b/lib/gdx-backend-lwjgl3.jar.gz deleted file mode 100644 index 2a391f5..0000000 --- a/lib/gdx-backend-lwjgl3.jar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:95f27e027b825dfb4603b5efcdfb3e68e0cdd45a5653e11fbba7c25e79df87db -size 1691011 diff --git a/lib/gdx-controllers-desktop-natives.jar b/lib/gdx-controllers-desktop-natives.jar deleted file mode 100644 index 0136285..0000000 Binary files a/lib/gdx-controllers-desktop-natives.jar and /dev/null differ diff --git a/lib/gdx-controllers-desktop.jar b/lib/gdx-controllers-desktop.jar deleted file mode 100644 index 8a7c85d..0000000 Binary files a/lib/gdx-controllers-desktop.jar and /dev/null differ diff --git a/lib/gdx-controllers-lwjgl3.jar.gz b/lib/gdx-controllers-lwjgl3.jar.gz deleted file mode 100644 index a404999..0000000 --- a/lib/gdx-controllers-lwjgl3.jar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c5d6954efe7547a4ae86fd7cd27343a4ff8a3c1b5537e990e506af8e2c438707 -size 5541 diff --git a/lib/gdx-controllers.jar b/lib/gdx-controllers.jar deleted file mode 100644 index 1c24977..0000000 Binary files a/lib/gdx-controllers.jar and /dev/null differ diff --git a/lib/gdx-nightly-20170610.zip.gz b/lib/gdx-nightly-20170610.zip.gz deleted file mode 100644 index 6929e9e..0000000 --- a/lib/gdx-nightly-20170610.zip.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:30d86d6e6ed0ea725e7e8d4cd4bb9aa0ab1ef69c9e14eb557808cd8e2ace8737 -size 13760205 diff --git a/lib/gdx-nightly-20181111.zip.gz b/lib/gdx-nightly-20181111.zip.gz deleted file mode 100644 index e12f352..0000000 --- a/lib/gdx-nightly-20181111.zip.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e2d984a7706b6b047e5b4974090f66015afb864d0c3059959d8fc9a18b2fe558 -size 7840303 diff --git a/lib/gdx-nightly-20190112.zip.gz b/lib/gdx-nightly-20190112.zip.gz deleted file mode 100644 index bf3a8d8..0000000 --- a/lib/gdx-nightly-20190112.zip.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5d7c447e5f6f67191984aa7a3b93a40d7a31a93991659443eca4b685fc44423 -size 10005989 diff --git a/lib/gson-2.8.5.jar b/lib/gson-2.8.5.jar deleted file mode 100644 index 0d5baf3..0000000 Binary files a/lib/gson-2.8.5.jar and /dev/null differ diff --git a/lib/jogg-0.0.7.jar.gz b/lib/jogg-0.0.7.jar.gz deleted file mode 100644 index 983351b..0000000 --- a/lib/jogg-0.0.7.jar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:07108b22478debd82b3affbf17d8adfc0c95f71ec16898a080e6a777bcad3f63 -size 6122 diff --git a/lib/jopus.jar b/lib/jopus.jar deleted file mode 100644 index 6769732..0000000 Binary files a/lib/jopus.jar and /dev/null differ diff --git a/lib/jorbis-0.0.17.jar.gz b/lib/jorbis-0.0.17.jar.gz deleted file mode 100644 index f87a868..0000000 --- a/lib/jorbis-0.0.17.jar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ac3bed29268510d5f9dddadcf8e38fc77ffaca21df307ed73c108c6ef01f123 -size 94544 diff --git a/lib/jxinput-1.0.0.jar b/lib/jxinput-1.0.0.jar deleted file mode 100644 index 15ba084..0000000 Binary files a/lib/jxinput-1.0.0.jar and /dev/null differ diff --git a/lib/libjinput.zip.gz b/lib/libjinput.zip.gz deleted file mode 100644 index 10950c8..0000000 --- a/lib/libjinput.zip.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e69225c091ee28d6c48b94dbcccccb7b8b58420c82558ddd94e9f2cbc0f73377 -size 342469 diff --git a/lib/libjopus.so b/lib/libjopus.so deleted file mode 100644 index 37b9a79..0000000 Binary files a/lib/libjopus.so and /dev/null differ diff --git a/lib/prtree.jar b/lib/prtree.jar deleted file mode 100644 index 728a327..0000000 Binary files a/lib/prtree.jar and /dev/null differ