commit 708a36502bea3b289fa4eac46c93478a5af3eca3
Author: Emily Eisenberg <xymostech@gmail.com>
Date: Fri, 5 Jul 2013 02:05:33 -0700
Initial commit
Diffstat:
| A | .gitignore | | | 2 | ++ |
| A | Makefile | | | 8 | ++++++++ |
| A | build.js | | | 163 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | index.html | | | 13 | +++++++++++++ |
| A | package.json | | | 7 | +++++++ |
| A | parser.jison | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | style.css | | | 98 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
7 files changed, 372 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,2 @@
+parser.js
+node_modules
diff --git a/Makefile 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
@@ -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
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+ <head>
+ <title>MJLite Test</title>
+ <script src="parser.js" type="text/javascript"></script>
+ <script src="build.js" type="text/javascript"></script>
+ <link href="style.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
+ <input type="text" value="2x^2 + 3" id="input" />
+ <div id="math"></div>
+ </body>
+</html>
diff --git a/package.json 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
@@ -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 '\\'
+<<EOF>> 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
@@ -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;
+}