<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="style.css" />
<script data-require="jquery" data-semver="2.0.3" src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<h2>Javascript RPN (Reverse Polish Notation) with Shunting Yard implementation by Paul Lan</h2>
<h3>Input your Expression here:</h3>
<input id="expression_input" value="( a || b ) && ( c && ( d || e) )" placeholder="Support &&, ||, (, ) " size="50" />
<div>
<h3>Parsed output</h3>
<div id="output"></div>
</div>
<p />
<hr />
<h3>Reference: </h3>
<ol>
<li> RPN:
<a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation">http://en.wikipedia.org/wiki/Reverse_Polish_notation</a></li>
<li> Shunting Yard:
<a href="http://en.wikipedia.org/wiki/Shunting-yard_algorithm">http://en.wikipedia.org/wiki/Shunting-yard_algorithm</a>
</li>
</body>
</html>
// Add your javascript here
var FIELDSPLITER = ':'; // forRPN: N;
var FIELDSPLITERPattern = /:/; // forRPN: N;
var AND = '&&'; // forRPN: Y; priority: 2
var ANDForReg = '\\&\\&'; // forRPN: Y; priority: 2
var OR = '||'; // forRPN: Y; priority: 3
var ORForReg = '\\|\\|'; // forRPN: Y; priority: 3
var LEFTPS = '('; // forRPN: Y; priority: Left parenthesis
var LEFTPSForReg = '\\('; // forRPN: Y; priority: Left parenthesis
var RIGHTPS = ')'; // forRPN: Y; priority: right parenthesis
var RIGHTPSForReg = '\\)'; // forRPN: Y; priority: right parenthesis
var fieldListPatternStr = '[^' + AND + OR + LEFTPS + RIGHTPS + ']+'; // valid field pattern
var splitterList = [OR, AND, LEFTPS, RIGHTPS];
var splitterListRegExp = [ORForReg, ANDForReg, LEFTPSForReg, RIGHTPSForReg];
var splitterListPattern = new RegExp(splitterListRegExp.join('|') + '|' + fieldListPatternStr, 'g');
var fieldListRegExp = new RegExp(fieldListPatternStr, 'g');
var operatorListPattern = new RegExp(splitterListRegExp.join('|'));
var RPNPriorityGroup = {};
RPNPriorityGroup[OR] = 3;
RPNPriorityGroup[AND] = 2;
var ANDORPattern = new RegExp(ANDForReg + '|' + ORForReg);
var makeRPN = function(inputValue) {
if (!inputValue) {
return false;
}
var inputRPN = [];
inputRPN = inputValue.match(splitterListPattern);
var tmpStackRPN = [];
var outputRPN = [];
// there are some unpaired parenthesis in the input
var isUnPairedPs = false;
var utils = {
pushToOutput: function(item) {
outputRPN.push(item);
},
topOfTmpStack: function() {
return tmpStackRPN[tmpStackRPN.length - 1]
},
popItemOfStackToOutputRPNUntilLeftPs: function(indexOfItemInInputRPN) {
var item;
while ((item = tmpStackRPN.pop()) !== LEFTPS) {
utils.pushToOutput(item);
}
if (typeof item === 'undefined' && !tmpStackRPN.length && (indexOfItemInInputRPN === inputRPN.length - 1)) {
// un pair parenthesis
isUnPairedPs = true;
}
},
popAllItemOfStack: function() {
var item;
while (item = tmpStackRPN.pop()) {
if (item === LEFTPS) {
isUnPairedPs = true;
} else {
utils.pushToOutput(item);
}
}
}
};
var top;
for (var i = 0, element; i < inputRPN.length; i++) {
element = inputRPN[i].trim();
if (operatorListPattern.test(element)) {
// all operators
if (element === LEFTPS) {
// left parenthesis
tmpStackRPN.push(element);
} else if (element === RIGHTPS) {
// right parenthesis
utils.popItemOfStackToOutputRPNUntilLeftPs(i);
} else {
// if the input operator priority is <= outputUtil.top()
top = utils.topOfTmpStack();
// for operator with priority (not parenthesis)
if (top && (top != LEFTPS) && RPNPriorityGroup[element] <= RPNPriorityGroup[top]) {
utils.pushToOutput(tmpStackRPN.pop());
tmpStackRPN.push(element);
} else {
tmpStackRPN.push(element);
}
}
} else {
// text
// remove empty string
if (element !== '') {
utils.pushToOutput(element);
}
}
}
// pop out the rest stacked operator
utils.popAllItemOfStack();
return !isUnPairedPs && outputRPN || false;
}
$(function() {
var $input = $('#expression_input');
var parseIt = function() {
$('#output').html(makeRPN($input.val()));
// debugger;
};
$input.keyup(parseIt);
parseIt();
});
/* Put your css in here */
h2 {
color: blue;
}
#output {
letter-spacing: 3px;
}