commit 708a36502bea3b289fa4eac46c93478a5af3eca3 Author: Emily Eisenberg Date: Fri Jul 5 02:05:33 2013 -0700 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..38e02923 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +parser.js +node_modules diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..75ab1430 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +FILES=parser.js style.css build.js index.html + +.PHONY: ship +ship: parser.js + scp $(FILES) prgmr:/var/www/www.rampancylabs.com/parser/ + +parser.js: parser.jison + ./node_modules/.bin/jison parser.jison diff --git a/build.js b/build.js new file mode 100644 index 00000000..3404dc95 --- /dev/null +++ b/build.js @@ -0,0 +1,163 @@ +var doParse = function(toparse, baseelem) { + var makeex = function(ex, base) { + for (var i = 0; i < ex.length; i++) { + var prev = i > 0 ? ex[i-1] : null; + var group = makegroup(ex[i], prev); + base.appendChild(group); + } + + return base; + }; + + var makegroup = function(group, prev) { + if (group.type === "ord") { + var elem = document.createElement("span"); + elem.className = "mord"; + elem.appendChild(mathit(group.value)); + return elem; + } else if (group.type === "bin") { + var elem = document.createElement("span"); + if (prev == null || prev.type === "bin" || prev.type === "open") { + group.type = "ord"; + elem.className = "mord"; + } else { + elem.className = "mbin"; + } + elem.appendChild(mathit(group.value)); + return elem; + } else if (group.type === "sup") { + var elem = document.createElement("span"); + elem.className = "mord"; + makeex(group.value.base, elem); + + var sup = document.createElement("span"); + sup.className = "msup"; + makeex(group.value.sup, sup); + + elem.appendChild(sup); + + return elem; + } else if (group.type === "sub") { + var elem = document.createElement("span"); + elem.className = "mord"; + makeex(group.value.base, elem); + + var sub = document.createElement("span"); + sub.className = "msub"; + makeex(group.value.sub, sub); + + elem.appendChild(sub); + + return elem; + } else if (group.type === "supsub") { + var elem = document.createElement("span"); + elem.className = "mord"; + makeex(group.value.base, elem); + + var supsub = document.createElement("span"); + supsub.className = "msupsub"; + + var sup = document.createElement("span"); + sup.className = "msup"; + makeex(group.value.sup, sup); + + var sub = document.createElement("span"); + sub.className = "msub"; + makeex(group.value.sub, sub); + + supsub.appendChild(sup); + supsub.appendChild(sub); + + elem.appendChild(supsub); + + return elem; + } else if (group.type === "open") { + var elem = document.createElement("span"); + elem.className = "mopen"; + elem.appendChild(mathit(group.value)); + return elem; + } else if (group.type === "close") { + var elem = document.createElement("span"); + elem.className = "mclose"; + elem.appendChild(mathit(group.value)); + return elem; + } else if (group.type === "cdot") { + var elem = document.createElement("span"); + elem.className = "mbin"; + elem.appendChild(textit('\u22C5')); + return elem; + } else if (group.type === "frac") { + var frac = document.createElement("span"); + frac.className = "mord mfrac"; + + var numer = document.createElement("span"); + numer.className = "mfracnum"; + makeex(group.value.numer, numer); + + var mid = document.createElement("span"); + mid.className = "mfracmid"; + mid.appendChild(document.createElement("span")); + + var denom = document.createElement("span"); + denom.className = "mfracden"; + makeex(group.value.denom, denom); + + frac.appendChild(numer); + frac.appendChild(mid); + frac.appendChild(denom); + + return frac; + } else { + console.log(group.type); + } + }; + + var charLookup = { + '*': '\u2217', + '-': '\u2212', + 'cdot': '\u22C5' + }; + + var textit = function(value) { + if (value in charLookup) { + value = charLookup[value]; + } + return document.createTextNode(value); + }; + + var mathit = function(value) { + var text = textit(value); + + if (/[a-zA-Z]/.test(value)) { + var elem = document.createElement("span"); + elem.className = "mathit"; + elem.appendChild(text); + return elem; + } else { + return text; + } + }; + + var tree = parser.parse(toparse); + clearNode(baseelem); + makeex(tree, baseelem); +}; + +var clearNode = function(node) { + var children = node.childNodes; + for (var i = children.length - 1; i >= 0; i--) { + console.log(children[i]); + node.removeChild(children[i]); + } +}; + +window.onload = function() { + var input = document.getElementById("input"); + var math = document.getElementById("math"); + + doParse(input.value, math); + + input.oninput = function() { + doParse(input.value, math); + }; +}; diff --git a/index.html b/index.html new file mode 100644 index 00000000..36edfd78 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + MJLite Test + + + + + + +
+ + diff --git a/package.json b/package.json new file mode 100644 index 00000000..bf38a433 --- /dev/null +++ b/package.json @@ -0,0 +1,7 @@ +{ + "name": "mjlite", + "version": "0.0.1", + "devDependencies": { + "jison": "~0.4.6" + } +} diff --git a/parser.jison b/parser.jison new file mode 100644 index 00000000..b6ea5216 --- /dev/null +++ b/parser.jison @@ -0,0 +1,81 @@ +/* description: Parses end executes mathematical expressions. */ + +/* lexical grammar */ +%lex +%% + +\s+ /* skip whitespace */ +cdot return 'CDOT' +frac return 'FRAC' +[/a-zA-Z0-9] return 'ORD' +[*+-] return 'BIN' +\^ return '^' +[_] return '_' +[{] return '{' +[}] return '}' +[(] return 'OPEN' +[)] return 'CLOSE' +[\\] return '\\' +<> return 'EOF' + +/lex + +/* operator associations and precedence */ + +%left '^' +%left '_' +%left 'ORD' +%left 'BIN' +%left SUPSUB + +%start expression + +%% /* language grammar */ + +expression + : ex EOF + {return $1;} + ; + +ex + : + {$$ = [];} + | group ex + {$$ = $1.concat($2);} + | group '^' group ex + {$$ = [{type: 'sup', value: {base: $1, sup: $3}}].concat($4);} + | group '_' group ex + {$$ = [{type: 'sub', value: {base: $1, sub: $3}}].concat($4);} + | group '^' group '_' group ex %prec SUPSUB + {$$ = [{type: 'supsub', value: {base: $1, sup: $3, sub: $5}}].concat($6);} + | group '_' group '^' group ex %prec SUPSUB + {$$ = [{type: 'supsub', value: {base: $1, sup: $5, sub: $3}}].concat($6);} + ; + +group + : atom + {$$ = $1;} + | '{' ex '}' + {$$ = $2;} + | '\\' func + {$$ = $2;} + ; + +func + : 'CDOT' + {$$ = [{type: 'bin', value: yytext}];} + | 'FRAC' group group + {$$ = [{type: 'frac', value: {numer: $2, denom: $3}}];} + ; + +atom + : 'ORD' + {$$ = [{type: 'ord', value: yytext}];} + | 'BIN' + {$$ = [{type: 'bin', value: yytext}];} + | 'OPEN' + {$$ = [{type: 'open', value: yytext}];} + | 'CLOSE' + {$$ = [{type: 'close', value: yytext}];} + ; + diff --git a/style.css b/style.css new file mode 100644 index 00000000..0c53c9a6 --- /dev/null +++ b/style.css @@ -0,0 +1,98 @@ +@font-face { + font-family: MathJax_Main; + src: url("http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Main-Regular.otf"); +} + +@font-face { + font-family: MathJax_Main; + src: url("http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Main-Italic.otf"); + font-style: italic; +} + +@font-face { + font-family: MathJax_Math; + src: url("http://cdn.mathjax.org/mathjax/latest/fonts/HTML-CSS/TeX/otf/MathJax_Math-Italic.otf"); + font-style: italic; +} + +/* +thin space: 1/6 quad +medium space: 2/9 quad +thick space: 5/18 quad + +things to do: +^ _ and styles +\sin +\sum, \int, \lim +\frac +\sqrt +big parens +*/ + +body { + margin: 0px; + padding: 0px; +} + +input { + margin: 0px; + font-size: 100%; +} + +#math { + font-family: MathJax_Main; +} + +.mathit { + font: italic 100% MathJax_Math; +} + +.mord + .mbin { + margin-left: 0.22222em; +} + +.mbin + .mord { + margin-left: 0.22222em; +} + +.msub { + vertical-align: bottom; + font-size: 70%; + position: relative; + top: 0.2em; +} + +.msup { + position: relative; + top: -0.5em; + font-size: 70%; +} + +.msupsub { + display: inline-table; + table-layout: fixed; + vertical-align: middle; +} + +.msupsub > .msup, .msupsub > .msub { + display: table-row; + vertical-align: baseline; + line-height: 1em; +} + +.mfrac { + display: inline-table; + vertical-align: 0.88em; +} + +.mfracnum, .mfracmid, .mfracden { + display: table-row; + text-align: center; +} + +.mfracmid > span { + background: black; + display: block; + height: 0.05em; + min-height: 1px; +}