UNPKG

kas-npm

Version:

A lightweight JavaScript CAS for comparing expressions and equations. Forked from @Khan to use in NPM.

223 lines (214 loc) 10.9 kB
#!/usr/bin/env node /* TODO(charlie): fix these lint errors (http://eslint.org/docs/rules): */ /* eslint-disable no-var, comma-dangle, max-len, comma-spacing */ var fs = require("fs"); var path = require("path"); var jison = require("jison"); var grammar = { lex: { rules: [ ["\\s+", "/* skip whitespace */"], ["\\\\space", "/* skip \\space */"], ["\\\\ ", "/* skip '\\ ' */"], ["[0-9]+\\.?", "return \"INT\""], ["([0-9]+)?\\.[0-9]+", "return \"FLOAT\""], ["\\*\\*", "return \"^\""], ["\\*", "return \"*\""], ["\\\\cdot|\u00b7", "return \"*\""], ["\\\\times|\u00d7", "return \"*\""], ["\\\\ast", "return \"*\""], ["\\/", "return \"/\""], ["\\\\div|\u00F7", "return \"/\""], ["-", "return \"-\""], ["\u2212", "return \"-\""], // minus ["\\+", "return \"+\""], ["\\^", "return \"^\""], ["\\(", "return \"(\""], ["\\)", "return \")\""], ["\\\\left\\(", "return \"(\""], ["\\\\right\\)", "return \")\""], ["\\[", "return \"[\""], ["\\]", "return \"]\""], ["\\{", "return \"{\""], ["\\}", "return \"}\""], ["\\\\left\\{", "return \"{\""], ["\\\\right\\}", "return \"}\""], ["_", "return \"_\""], ["\\|", "return \"|\""], ["\\\\left\\|", "return \"LEFT|\""], ["\\\\right\\|", "return \"RIGHT|\""], ["\\!", "return \"!\""], // not yet interpreted ["<=|>=|<>|<|>|=", "return \"SIGN\""], ["\\\\le", "yytext = \"<=\"; return \"SIGN\""], ["\\\\ge", "yytext = \">=\"; return \"SIGN\""], ["\\\\leq", "yytext = \"<=\"; return \"SIGN\""], ["\\\\geq", "yytext = \">=\"; return \"SIGN\""], ["=\\/=", "yytext = \"<>\"; return \"SIGN\""], ["\\\\ne", "yytext = \"<>\"; return \"SIGN\""], ["\\\\neq", "yytext = \"<>\"; return \"SIGN\""], ["\u2260", "yytext = \"<>\"; return \"SIGN\""], // ne ["\u2264", "yytext = \"<=\"; return \"SIGN\""], // le ["\u2265", "yytext = \">=\"; return \"SIGN\""], // ge ["\\\\frac", "return \"FRAC\""], ["\\\\dfrac", "return \"FRAC\""], ["sqrt|\\\\sqrt", "return \"sqrt\""], ["abs|\\\\abs", "return \"abs\""], ["ln|\\\\ln", "return \"ln\""], ["log|\\\\log", "return \"log\""], ["sin|cos|tan", "return \"TRIG\""], ["csc|sec|cot", "return \"TRIG\""], ["sinh|cosh|tanh", "return \"TRIG\""], ["csch|sech|coth", "return \"TRIG\""], ["\\\\sin", "yytext = \"sin\"; return \"TRIG\""], ["\\\\cos", "yytext = \"cos\"; return \"TRIG\""], ["\\\\tan", "yytext = \"tan\"; return \"TRIG\""], ["\\\\csc", "yytext = \"csc\"; return \"TRIG\""], ["\\\\sec", "yytext = \"sec\"; return \"TRIG\""], ["\\\\cot", "yytext = \"cot\"; return \"TRIG\""], ["\\\\arcsin", "yytext = \"arcsin\"; return \"TRIG\""], ["\\\\arccos", "yytext = \"arccos\"; return \"TRIG\""], ["\\\\arctan", "yytext = \"arctan\"; return \"TRIG\""], ["\\\\arccsc", "yytext = \"arccsc\"; return \"TRIG\""], ["\\\\arcsec", "yytext = \"arcsec\"; return \"TRIG\""], ["\\\\arccot", "yytext = \"arccot\"; return \"TRIG\""], ["arcsin|arccos|arctan","return \"TRIGINV\""], ["arccsc|arcsec|arccot","return \"TRIGINV\""], ["\\\\sinh", "yytext = \"sinh\"; return \"TRIG\""], ["\\\\cosh", "yytext = \"cosh\"; return \"TRIG\""], ["\\\\tanh", "yytext = \"tanh\"; return \"TRIG\""], ["\\\\csch", "yytext = \"csch\"; return \"TRIG\""], ["\\\\sech", "yytext = \"sech\"; return \"TRIG\""], ["\\\\coth", "yytext = \"tanh\"; return \"TRIG\""], ["pi", "return \"CONST\""], ["\u03C0", "yytext = \"pi\"; return \"CONST\""], // pi ["\\\\pi", "yytext = \"pi\"; return \"CONST\""], ["theta", "return \"VAR\""], ["\u03B8", "yytext = \"theta\"; return \"VAR\""], // theta ["\\\\theta", "yytext = \"theta\"; return \"VAR\""], ["phi", "return \"VAR\""], ["\u03C6", "yytext = \"phi\"; return \"VAR\""], // phi ["\\\\phi", "yytext = \"phi\"; return \"VAR\""], ["[a-zA-Z]", "return yy.symbolLexer(yytext)"], ["$", "return \"EOF\""], [".", "return \"INVALID\""] ], options: { flex: true // pick longest matching token } }, operators: [ ["right", "|"], ["left", "+", "-"], ["left", "*", "/"], ["left", "UMINUS"], ["right", "^"] ], start: "equation", bnf: { "equation": [ ["expression SIGN expression EOF", "return new yy.Eq($1, $2, $3);"], ["expression EOF", "return $1;"], ["EOF", "return new yy.Add([]);"] ], "expression": [ ["additive", "$$ = $1;"] ], "additive": [ ["additive + multiplicative", "$$ = yy.Add.createOrAppend($1, $3);"], ["additive - multiplicative", "$$ = yy.Add.createOrAppend($1, yy.Mul.handleNegative($3, \"subtract\"));"], ["multiplicative", "$$ = $1;", {prec: "+"}] ], "multiplicative": [ // the second term in an implicit multiplication cannot be negative ["multiplicative triglog", "$$ = yy.Mul.fold(yy.Mul.createOrAppend($1, $2));"], ["multiplicative * negative", "$$ = yy.Mul.fold(yy.Mul.createOrAppend($1, $3));"], ["multiplicative / negative", "$$ = yy.Mul.fold(yy.Mul.handleDivide($1, $3));"], ["negative", "$$ = $1;"] ], "negative": [ ["- negative", "$$ = yy.Mul.handleNegative($2);", {prec: "UMINUS"}], ["triglog", "$$ = $1;"] ], "trig": [ ["TRIG", "$$ = [yytext];"] ], "trigfunc": [ ["trig", "$$ = $1;"], ["trig ^ negative", "$$ = $1.concat($3);"], ["TRIGINV", "$$ = [yytext];"] ], "logbase": [ ["ln", "$$ = yy.Log.natural();"], ["log", "$$ = yy.Log.common();"], ["log _ subscriptable", "$$ = $3;"] ], "triglog": [ ["trigfunc negative", "$$ = yy.Trig.create($1, $2);"], ["logbase negative", "$$ = yy.Log.create($1, $2);"], ["power", "$$ = $1;"] ], "power": [ ["primitive ^ negative", "$$ = new yy.Pow($1, $3);"], ["primitive", "$$ = $1;"] ], "variable": [ ["VAR", "$$ = yytext;"] ], "subscriptable": [ ["variable _ subscriptable", "$$ = new yy.Var($1, $3);"], ["variable", "$$ = new yy.Var($1);"], ["CONST", "$$ = new yy.Const(yytext.toLowerCase());"], ["INT", "$$ = yy.Int.create(Number(yytext));"], ["FLOAT", "$$ = yy.Float.create(Number(yytext));"], ["{ additive }", "$$ = $2.completeParse();"], ["( additive )", "$$ = $2.completeParse().addHint('parens');"] // this probably shouldn't be a hint... ], "function": [ ["FUNC", "$$ = yytext;"] ], "invocation": [ ["sqrt ( additive )", "$$ = yy.Pow.sqrt($3);"], ["sqrt { additive }", "$$ = yy.Pow.sqrt($3);"], ["sqrt [ additive ] { additive }", "$$ = new yy.Pow.nthroot($6, $3);"], ["abs ( additive )", "$$ = new yy.Abs($3);"], ["| additive |", "$$ = new yy.Abs($2);"], ["LEFT| additive RIGHT|", "$$ = new yy.Abs($2);"], ["function ( additive )", "$$ = new yy.Func($1, $3);"] ], "primitive": [ ["subscriptable", "$$ = $1;"], ["invocation", "$$ = $1;"], ["FRAC { additive } { additive }", "$$ = yy.Mul.handleDivide($3, $6);"] ] } }; var prelude = "// This is a @gene" + "rated file\n" + "var _, KAS = {};\n\n" + "if (typeof module === \"object\" && module.exports) {\n" + " _ = require(\"underscore\");\n" + " module.exports = KAS;\n" + "} else {\n" + " _ = window._;\n" + " window.KAS = KAS;\n" + "}\n\n" + "(function(KAS) {\n\n"; var parser = (new jison.Generator(grammar)).generate({moduleType: "js"}); // NOTE(jeresig): We need to comment out these two labels as they appear to be // invalid ES5 (they also aren't referenced anywhere so this seems safe). parser = parser.replace(/(_token_stack:)/g, "//$1"); var postlude = "\n\nKAS.parser = parser;\n})(KAS);"; fs.writeFileSync(path.resolve(__dirname, "parser.js"), prelude + parser + postlude); var unitPrelude = "// this is a @gene" + "rated file\n" + "(function(KAS) {\n\n"; var unitEpilogue = "\n\nKAS.unitParser = parser;\n" + "})(KAS);"; var unitParserInfile = path.resolve(__dirname, "unitvalue.jison"); var unitParserOutfile = path.resolve(__dirname, "unitparser.js"); var unitParserSource = fs.readFileSync(unitParserInfile); var unitParser = new jison.Generator(unitParserSource.toString()); var generatedParser = unitParser.generate({ moduleType: "js" }); // NOTE(jeresig): We need to comment out these two labels as they appear to be // invalid ES5 (they also aren't referenced anywhere so this seems safe). generatedParser = generatedParser.replace(/(_token_stack:)/g, "//$1"); fs.writeFileSync(unitParserOutfile, unitPrelude + generatedParser + unitEpilogue);