+
1
|
list
|
skin
|
login
|
editor
α-wwwiki
::
basic_evaluator
user:none
(4413 bytes)
_h1 basic evaluator {sup (1)} {div {@ style="text-align:center; color:red; background:#eee;box-shadow:0 0 8px black;"} basic eval | [[extended eval|?view=extended_evaluator]] | [[regexp eval|?view=regexp_evaluator]] | [[alpha lisp|?view=lisp_evaluator]] | [[monodico lisp|?view=monodicolisp]] } _p The basic evaluator evaluates valid s-expressions built on a reduced dictionary of primitives functions : {b +, *, -, /, sqrt, pow, square, hypo, fac}. For an extended evaluator with much more functions and a "define" operator, see [[extended_evaluator]]. _p Each s-expression is transformed in a nested array via two functions, tokenize() and build_tree(), which is recursively evaluated down to the primitive functions. Several s-expressions can be evaluated in sequence provided they are embedded in a (begin ....) s-expression. _h3 console _p This is how to use the console : _ul First click only once on the "init the evaluator", _ul type any s-expression in the input textarea, _ul then click on the button "evaluate" and do it again with new values. {textarea {@ id="input" style="width:99%; height:200px; font:normal 1em courier; color:red; background:#ffc;"} (begin (+ 1 2) (* 1 2 3 4 5 6) (sqrt (+ (* 3 3) (* 4 4) ) ) ) } First {input {@ type="submit" value="init evaluator" onclick="°° var js = document.createElement('script'); var input = getId('code').innerHTML; js.innerHTML = decode_html_entities(input); // < ,> document.head.appendChild( js ); this.value = 'OK, evaluator inited !'; this.disabled='disabled'; °°"}} then {input {@ type="submit" value="evaluate" onclick="do_evaluate()"}} {pre {@ id="output"}} _h3 examples {pre (+ 1 2 3 4 5 6) (* 1 2 3 4 5 6) (+ (* 3 3( (* 4 4)) (* (+ 3 3) (+ 4 4)) (sqrt 2) (pow' 2 8) (sqrt (+ (* 3 3) (* 4 4))) (hypo 3 4) (fac 6) } _h3 evaluator's code {pre {@ id="code"}°° // HTML interface function do_evaluate() { getId('output').innerHTML = BASIC_EVAL.parser(getId('input').value); } var BASIC_EVAL = (function () { // 1) parser var parser = function (str) { return evaluate(build_tree(tokenize(str))) }; var tokenize = function ( s ) { return s.replace(/\(/g, ' ( ') .replace(/\)/g, ' ) ') .trim() .split(/\s+/); }; var build_tree = function (tokens) { var token = tokens.shift(); if (token !== '(') return token; var arr = [], i = 0; while (tokens[0] !== ')') { i++ ; if (i>10000) return 'unbalanced s-expression : game over !'; arr.push( build_tree(tokens) ); } tokens.shift(); return arr; }; // 2) evaluator var evaluate = function(expression) { var first = '', rest = []; if (!Array.isArray(expression)) return expression.toString(); first = expression.shift(); if (dico.hasOwnProperty(first)) { expression.map(function(a){rest.push(evaluate(a))}) return dico[first].apply(null,rest); } return 'Sorry, [' + first + '] is unknown !'; }; // 3) dictionary var dico = {}; dico['begin'] = function () { return [].slice.call(arguments).join(' ').replace(/ /g, '\n') }; // basic operators dico['+'] = function() { for (var r=0, i=0; i< arguments.length; i++) r += Number(arguments[i]); return r; }; dico['*'] = function() { for (var r=1, i=0; i< arguments.length; i++) r *= arguments[i]; return r; }; dico['-'] = function () { // (- 1 2 3 4) -> 1-2-3-4 var r = arguments[0]; if (arguments.length == 1) r = -r; // case (- 1) -> -1 else for (var i=1; i< arguments.length; i++) r -= arguments[i]; return r; }; dico['/'] = function () { // (/ 1 2 3 4) -> 1/2/3/4 var r = arguments[0]; if (arguments.length == 1) r = 1/r; // case (/ 2) -> 1/2 else for (var i=1; i< arr.length; i++) r /= arguments[i]; return r; }; // a few JS Math and custom fuctions dico['sqrt'] = function(a) { return Math.sqrt( a ) }; dico['pow'] = function(a) { return Math.pow( a[0], a[1] ) }; dico['square'] = function(a) { return a[0]*a[0] }; dico['hypo'] = function(a) { return Math.sqrt( a[0]*a[0] + a[1]*a[1] ) }; dico['fac'] = function(a) { return (a< 2)? 1 : a*arguments.callee(a-1); }; // and so on. return {parser:parser}; }()); // end BASIC_EVAL °°}