4.5.08

Javascript recursive descent parser generator

Here is a recursive descent parser generator for javascript. As always, I'm too lazy to document how it works. I did not test it much. Just play with it if you like.

In the first section, you define the tokens. There is a special token called SKIP, which is ignored.

In the second section, you define the grammar of your language. Some examples:

C = { 
  A A;
  B;
};
means C is A followed by A, or C is B.

You can add types to your productions:

C = { 
  [A_PAIR] A A;
  [JUST_B] B;
};

You can name the symbols in the productions:

C = { 
  [A_PAIR] first:A second:A;
  [JUST_B] value:B;
};
Say that A denotes the token /[a-z]/, than the parse result of "x y" is an object like this:
{ Type: "A_PAIR", first:"x", second:"y" }

You can omit braces if there is only one production for a rule:

C = A A;

You can also inherit the parse result of a sub-rule. So instead of:

C = A A;
X = lbrace value:C rbrace;
then using x.value.first, you can do:
C = A A;
X = lbrace #C rbrace;
then use x.first.

You can also use wildcards in restricted cases:

Alist = A+;
Blist = B*;
in which case the result object will be an array.

22.12.07

Serializing JavaScript objects

I once have written a JavaScript function that dumps a JavaScript object in a human readable format. It was something like JSON, but it also handled objects containing circular references shared object references. I must admit that it was written badly.

After reading this, I thought that maybe it's a good idea to change the previous code for serializing JavaScript objects. I also refactored the code. You can find it below. I didn't test it thoroughly, so be careful.

An example of what it can do:
var x = {};

x.foo  = new Object();
x.self = x;
x.arr  = [x.self];
x.bar  = x.foo;

var s = serialize(x);
var y = deserialize(s);
alert(y == y.self);    // true
alert(y == y.arr[0]);  // true
alert(y.foo == y.bar); // true

alert(s);
// {
//     'foo': {},
//     'self': { _root_: [  ] },
//     'arr': [
//         { _root_: [  ] }
//     ],
//     'bar': { _root_: [ "foo" ] }
// }
Addition: I think that I have to express that better: don't expect it to serialize functions, regular expressions, images (or any other browser object), etc. It's just something like JSON, but it also handles shared object references. Code:
//============================================================================//
//  JavaScript object de/serialization with circular references.              //
//                                                                            //
//  author: Mehmet Yavuz Selim Soyturk                                        //
//  e-mail: Mehmet dot Yavuz dot Selim at gmail dot com                       //
//============================================================================//

Array.prototype.findIf = function(predicate) {
    for(var i in this) {
        if (predicate(this[i]))
            return i;
    }
    return -1;
};
Array.prototype.map = function(func) {
    var len = this.length;
    var result = [];
    for (var i=0; i<len; i++) {
        result[i] = func(this[i]);
    }
    return result;
};
Array.prototype.appended = function(value) {
    var copy = this.slice(0);
    copy[copy.length] = value;
    return copy;
};

//============================================================================//
//  SERIALIZATION                                                             //
//============================================================================//

function indented(n) {
    var s = '';
    for(var i=0; i<n; i++) s += '    ';
    return s;
}

function serializePrimitive(value) {
    if (typeof value == 'string')
        return '"' + value + '"';
    else
        return '' + value;
}

function serializePrimitiveArray(arr) {
    var s = "[ ";
    s += arr.map(serializePrimitive).join(', ');
    s += " ]";
    return s;
}

function serializeArray(arr, seen, indices, depth) {
    if (arr.length == 0)
        return '[]';

    seen[seen.length] = {obj: arr, indices: indices};
    
    var result = '[\n';
    for (var i=0; i<arr.length; i++) {
        result += indented(depth + 1);
        result += serializeAny(arr[i], seen, indices.appended(i), depth + 1);
        result += (i == arr.length - 1) ? '' : ', ';
        result += '\n';
    }
    result += indented(depth) + ']';

    return result;
}

function serializeObject(obj, seen, indices, depth) {
    seen[seen.length] = {obj: obj, indices: indices};
    
    var result = '{\n';
    var count = 0;
    for (var i in obj) {
        if (typeof obj[i] != 'function') {
            count++;
            result += indented(depth+1);
            result += "'" + i + "': ";
            result += serializeAny(obj[i], seen, indices.appended(i), depth + 1);
            result += ", \n"; // bad hack, see next
        }
    }
    if (count > 0) {
        result = result.substring(0, result.length-3) + '\n'; // bad hack
        return result + indented(depth) + '}';
    }
    else {
        return '{}';
    }
}


function serializeAny(value, seen, indices, depth) {
    var t = typeof(value);
    var prevIndex;
    
    if (t == 'function') {
        throw new Error("Cannot serialize function. Keys from root: " + 
            serializePrimitiveArray(indices));
    }
    else if (t != 'object') {
        return serializePrimitive(value);
    }
    else if ( (prevIndex = seen.findIf
                    ( function(obj) { return obj.obj == value } )
              ) >= 0) {
        return '{ _root_: ' + serializePrimitiveArray(seen[prevIndex].indices) + ' }';
    }
    else if (value.constructor == Array) {
        return serializeArray(value, seen, indices, depth);
    }
    else {
        return serializeObject(value, seen, indices, depth);
    }
};

function serialize(obj) {
   return serializeAny(obj, [], [], 0);
}


//============================================================================//
//  DESERIALIZATION                                                           //
//============================================================================//

function followIndices(obj, indices) {
    for (var i=0; i<indices.length; i++)
        obj = obj[indices[i]];
        
    return obj;
}

function replaceRootRefs(obj, root) {
    if (typeof obj != 'object' || obj == null)
        return;
    
    for (var i in obj) {
        var prop = obj[i];
        if (typeof prop == 'object' && prop != null) {
            if ('_root_' in prop)
                obj[i] = followIndices(root, prop._root_);
            replaceRootRefs(prop, root);
        }
    }
}

function deserialize(str) {
    var obj = eval( '(' + str + ')' );
    if (str.indexOf('_root_') < 0)
        return obj;
    
    replaceRootRefs(obj, obj);
    return obj;
}

15.12.07

Kablosuz aglari dinlemek icin

Interface'i monitor moda getir:
$ sudo iwconfig eth1 mode monitor
Wireshark'i calistir:
$ sudo wireshark
Dinle ve interface'i eski haline getir:
$ sudo iwconfig eth1 mode managed

13.12.07

latex, html, plain text

Converting latex to html, if the tex file has utf8 encoding:
latex2html -html_version 4,unicode document.tex
If you want only one page:
latex2html -split 0 -html_version 4,unicode document.tex
Converting html to plain tex:
elinks -dump document.html

16.11.07

Output buffer unwinding for PHP?

PHP 5 supports exception handling. When an exception occurs, PHP does stack unwinding so that it restores the state of the script... does it? No. An important state of the script does not get restored: the output. Would it not be a good idea if PHP also did some sort of output buffer unwinding? That is the idea:
<?php

exceptional_ob_start();

echo "Begin\n";
try {
    echo "Exception\n";
    throw new Exception();
} catch (Exception $e) {}
echo "End\n";

exceptional_ob_end_flush();
    
?>
And that is the only output:
Begin
End
I am not a PHP (nor webscripting) guy so I may be wrong, but I think that something like that would be very useful. It is maybe even needed for making PHP exceptions useful.
 

18.8.07

Currying in JavaScript

We can make our functions curried in JavaScript:
function curry(f, needed_len) {
    if (needed_len == undefined)
        needed_len = f.length;
        
    var curried = function() {
        var curried_args = arguments;
        if (curried_args.length >= needed_len) {
            return f.apply(this, arguments);
        }
        else {
            var curry_result_function = function() {
                var args = [];
                for(var i=0; i<curried_args.length; i++)
                    args[args.length] = curried_args[i];
                
                for(var i=0; i<arguments.length; i++)
                    args[args.length] = arguments[i];

                return f.apply(this, args);
            };
            return curry(curry_result_function, needed_len-curried_args.length);
        }
    };
    return curried;
}
And usage:
var curried_add = curry(function (a, b, c) {
    return a + b + c;
});

print(curried_add(1)(2)(3));
print(curried_add(1)()(2)()(3));
print(curried_add(1,2,3));
print(curried_add(1)(2,3));
print(curried_add(1,2)(3));
See also next pages for other implementations: http://www.dustindiaz.com/javascript-curry http://www.svendtofte.com/code/curried_javascript/
 
Note: after some more googling about currying in JavaScript, it's very interesting to see that http://www.coryhudson.com/blog/2007/03/10/javascript-currying-redux/ contains an almost identical implementation.

30.7.07

JavaScript'de eval ve closure'un gucu

Kendi halinde basit bir fonksiyonumuz olsun:
function myEval(code) {
    return eval(code);
}
Simdi kendimize bir sayac yapalim:
var inject = 'var n=0; var f=function(){return n++}; f';
var sayac = myEval(inject);

alert(sayac()); // 0
alert(sayac()); // 1
alert(sayac()); // 2