JSFiddle - React, Tailwind, and code Playground
HTML
<input id=expr value="1 + 1 = 3 ? no : 2 + 2 = 5 ? no : yes"/>
<button id=evaluate>Evaluate</button>
<h3>Result</h3>
<div id=result>???</div>
<h3>AST</h3>
<div id=ast></div>
CSS
body, input, button {
font-size: 14pt;
font-family: monospace;
}
.hover {
background-color: #eee;
}
.hover .inner {
background-color: #fff;
}
h3 {
margin-bottom: 0px;
}
.inner {
display: inline-block;
border: 1px solid #888;
border-radius: 8px;
padding: 3px;
margin: 3px;
}
.id {
color: #a55;
font-weight: bold;
}
.num {
color: #008;
font-weight: bold;
}
.op {
padding: 3px;
}
JavaScript
var op_re = "([\\(\\)\\[\\]\\{\\}]|[!@#$%^&*|/?:~+=<>-]+)"
var id_re = "([A-Za-z_][A-Za-z_0-9]*)"
var num_re = "([0-9]+)"
var str_re = "(\"(?:[^\"]|\\\\.)*\")"
var re = new RegExp([op_re, id_re, num_re, str_re, "([^ \n])"].join("|"), "g");
var toktypes = ["op", "id", "num", "str", "other"];
function tokenize(text) {
var m;
var results = [{token: "$", type: "boundary"}];
var last = "op";
while (m = re.exec(text)) {
var type = toktypes[m.slice(1).indexOf(m[0])];
var tok = {token: m[0], type: type};
if (last.type === "op" && type === "op" && !getPrio(last)[2])
tok.prefix = true;
results.push(tok);
last = tok;
}
results.push({token: "$", type: "boundary"});
return results;
}
function oparse(next, order, finalize) {
var stack = [];
var between = null;
var left = next();
var right = next();
var current = [null, left];
while (true) {
switch (order(left, right)) {
case "done":
return between;
case "<•":
stack.push(current);
current = [between, right];
between = null;
left = right;
right = next();
break;
case "•>":
current.push(between);
between = finalize(current);
current = stack.pop()
left = current[current.length - 1];
break;
case "=•":
current.push(between, right);
between = null;
left = right;
right = next();
break;
}
}
}
priorities = {
"boundary:$": [-1, -1],
"type:id": [2000, 2000],
"type:num": [2000, 2000],
"op:(": [500, 0],
"op:P(": [500, 0],
"op:)": [0, 1000, true],
"op:P)": [0, 1000, true],
"op:[": [500, 0],
"op:P[": [500, 0],
...