Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Разное

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Кто поможет написать интерпретатор lisp?
 
 автор: Красная_шляпа   (20.12.2012 в 17:44)   письмо автору
 
 



<!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 operator( function(left, right) { 
            return left + right; 
        }, vargs );
    },
    
    '-': function(vargs) {      
        return operator( function(left, right) { 
            return left - right; 
        }, vargs );
    },
    
    '*': function(vargs) {      
        return operator( function(left, right) { 
            return left * right; 
        }, vargs );
    },
    
    '/': function(vargs) {      
        return operator( function(left, right) { 
            return left / right; 
        }, vargs );
    }
}

function operator(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>




Нужно: setq, defun и циклы по массивам.
Умеем: базовые математические операции, реализована локальная область видимости

Советы нужны любые

  Ответить  
 
 автор: cheops   (20.12.2012 в 21:44)   письмо автору
 
   для: Красная_шляпа   (20.12.2012 в 17:44)
 

Эээ... на JavaScript? Вообще lisp пишется на lisp, нужны только 5 базовых функций - все остальное строится восстанавливается из них. В СССР были даже LISP-машины, где в процессоры эти функции были реализованы в виде команд, а сам LISP служил своеобразным ассемблером... Ни в коем случае не критикую, но вы по полезности/эффективности пишите ассемблер на Basic... можно и полезно, но настоящего ассемблера у вас не получится... впрочем настоящий LISP мало где встречается, сплошь и рядом ядро уже предкомпилировано, а это влияет на динамические свойства языка.

PS Вообще возня вокруг LISP - это правильно, весело и здорово, но язык мягко говоря туго подходит для промышленной эксплуатации в современных условиях.

  Ответить  
 
 автор: Красная_шляпа   (20.12.2012 в 22:20)   письмо автору
 
   для: cheops   (20.12.2012 в 21:44)
 

самоцель не воссоздать язык с нуля а написать интерпретатор. лисп самый простой просто язык ну почти поэтому был выбран он. а так можно же любой язык реализовать( только придется использовать обратную польскую нотацию). а вообще я просто на википедии увидел processing.js это детище резига и компании язык со статической типизацией и решеткоподобным синтаксисом. а вообще есть реализации питона руби брейнфака и пр. недавно наткнулся на интерпретатор яваскрипт на самом же яваскрипт. есть интепретатор яваскрипт на питоне (9кб и 36кб) всего 36 кб весь яваскрипт уместился! да лисп древний язык ему 60 лет где то авторы и понятия не имели про ОПН наверное поэтому реализовали польскую нотацию префиксную. занимаясь этим казалось бы бесполезным делом можно понять принципы работы языка все мы говорим по русски но не задумываемся о правилах прежде чем что то сказать. так вот и кодить можно на чем угодно не понимая смысла

  Ответить  
 
 автор: Valick   (20.12.2012 в 22:43)   письмо автору
 
   для: Красная_шляпа   (20.12.2012 в 22:20)
 

кодить можно на чем угодно не понимая смысла
этим большая часть интернета забита... называется говнокодить :)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования