Initial commit
This commit is contained in:
commit
708a36502b
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
parser.js
|
||||
node_modules
|
8
Makefile
Normal file
8
Makefile
Normal file
|
@ -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
|
163
build.js
Normal file
163
build.js
Normal file
|
@ -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);
|
||||
};
|
||||
};
|
13
index.html
Normal file
13
index.html
Normal file
|
@ -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>
|
7
package.json
Normal file
7
package.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "mjlite",
|
||||
"version": "0.0.1",
|
||||
"devDependencies": {
|
||||
"jison": "~0.4.6"
|
||||
}
|
||||
}
|
81
parser.jison
Normal file
81
parser.jison
Normal file
|
@ -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}];}
|
||||
;
|
||||
|
98
style.css
Normal file
98
style.css
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user