Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title></title>
- <script type="text/javascript">
- var globalEnvironment = {
- 't': true,
- 'nil': false,
- '+': function(vargs) {
- return op( function(left, right) {
- return left + right;
- }, vargs );
- },
- '-': function(vargs) {
- return op( function(left, right) {
- return left - right;
- }, vargs );
- },
- '*': function(vargs) {
- return op( function(left, right) {
- return left * right;
- }, vargs );
- },
- '/': function(vargs) {
- return op( function(left, right) {
- return left / right;
- }, vargs );
- }
- }
- function op(cb, vargs) {
- if (vargs.length < 2) {
- throw 'требуется минимум 2 аргумента';
- }
- var i = 0, result = vargs[0];
- while (1) {
- if ( ++i == vargs.length ) {
- break;
- }
- result = cb( result, vargs[i] );
- }
- return result;
- }
- var parse = function(input) {
- // в js нет просмотра назад хз как всё описать с помощью одной регулярки
- var tokens = /;.*|"((?:[^"\\]|\\[\s\S])*)"|([^\s`();'",]{2,}|[^\s`();'",.])|(\S)/g,
- tok,
- expArr = [];
- function readToken() {
- var tok, i;
- while ( tok = tokens.exec(input) ) {
- for (i = 1; i < tok.length; ++i) {
- if ( tok[i] ) {
- return tok;
- }
- }
- }
- }
- function parseToken(tok) {
- if ( tok[1] ) {
- return [ 'string', tok[1].replace( /\\"/g, '"') ];
- }
- if ( tok[2] ) {
- if (tok[2] < 0 || tok[2] == 0 || tok[2] > 0) {
- return [ 'number', tok[2] * 1 ];
- }
- return [ 'word', tok[2].toLowerCase() ];
- }
- if (tok[3] == '(') {
- var arr = [ 'list', [] ];
- while ( tok = readToken() ) {
- if (tok[3] == ')') {
- return arr;
- }
- arr[1].push( parseToken(tok) );
- }
- throw 'Возможно, пропущена )';
- }
- throw 'Неожиданный токен ' + tok[3] + ' на позиции ' + tok.index;
- }
- while ( tok = readToken() ) {
- expArr.push( parseToken(tok) );
- }
- return expArr;
- }
- // new Environment( B, new Environment( A ) )
- //
- // undefined
- // \
- // A - data
- // \
- // B - data
- //
- // Где A, B - узлы. B.parent содержит ссылку на A.
- function Environment(data, parent) {
- this.data = data;
- this.parent = parent;
- }
- Environment.prototype.lookup = function(id) {
- var scope = this, data;
- while (scope) {
- if (scope.data[id] !== undefined) {
- return scope.data[id];
- }
- // если в текущем scope переменную не нашли смотрим на уровень выше
- scope = scope.parent;
- }
- throw 'Обьект ' + id + ' не найден';
- }
- function evaluate(exp, env) {
- switch ( exp[0] ) {
- case 'word':
- return env.lookup( exp[1] );
- case 'list':
- var name;
- exp = exp[1];
- name = exp[0][1];
- exp[0] = evaluate( exp[0], env );
- if ( typeof exp[0] == 'function' ) {
- for (var i = 1; i < exp.length; ++i) {
- exp[i] = evaluate( exp[i], env )
- }
- try {
- return exp[0].call(null, exp.slice(1), env);
- }
- catch (err) {
- throw 'Ошибка в функции ' + name + ': ' + err;
- }
- }
- throw '"' + name + '" не является функцией';
- default:
- return exp[1];
- }
- }
- function execute(input) {
- var expArr = parse(input),
- env = new Environment( {}, new Environment( globalEnvironment ) );
- alert( 'Подобие байт-кода:\n\n' + JSON.stringify(expArr) );
- for (var i = 0; i < expArr.length; ++i) {
- alert( evaluate(expArr[i], env) );
- }
- }
- // Ссылки:
- //
- // http://ru.wikipedia.org/wiki/Лексический_анализ
- // http://ru.wikipedia.org/wiki/Интерпретатор_(шаблон_проектирования)
- // http://ru.wikipedia.org/wiki/Польская_нотация
- // http://en.wikibooks.org/wiki/Common_Lisp/First_steps/Beginner_tutorial
- // http://www.csci.csusb.edu/dick/samples/lisp.lexemes.html
- var ge = function(id) {
- return document.getElementById(id);
- }
- window.addEventListener( 'load', function() {
- ge('execute').onclick = function() {
- try {
- execute( ge('input').value );
- }
- catch (err) {
- alert(err);
- }
- }
- } );
- </script>
- </head>
- <body>
- <textarea id="input"></textarea> <button id="execute">Выполнить!</button>
- </body>
- <script> // alert( document.getElementsByTagName('script')[0].innerText ); </script>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement