Manually parsing JSON before parsing to object

I'm creating a DSL based on JSON and JavaScript and I have a requirement to let key values be specified 'raw' and not enclosed in string delimiters. A quick example that hopefully explains this:

{myKey:custom_function('arg1'), myKey2:custom_function("another arg1")}

should become

{myKey:"custom_function('arg1')", myKey2:"custom_function(\"another arg1\")"}

This is because at the time of parsing the JSON object, custom_function will not exist. I need to be able to parse the JSON without evaluating any of the values, then only expand values one by one as I iterate the keys.

What regular expression or other method can I use to turn that 1st snippet into the 2nd one?

I'm assuming a simpler solution will cover 90% of cases but that writing a bullet-proof implementation would take a lot of effort. Based on the research I did into JavaScript's regular expression support (apparantly no lookbehind capability) I'm assuming it will require something more than just 1 or 2 lines of regex patterns.

Also, this is for a node application so any tricks that it has for this will be helpful too.

EDIT:

This question seems to be getting some downvotes, but I've left it up anyway for the benefit of future googlers / my own reference. It's a perfectly valid question about what method / technique would work best for this kind of problem, and there could easily be other node/js newcomers who face a similar problem.

Final answer: Regex just isn't suited to a task as complex as this. Any similarly complex solutions I found online (e.g. removing code comments) all resorted to a mainly custom, iterative approach, only using regex sparingly, so a similar approach ended up being not too painless in this situation.

So in the end the 'best' method I could find didn't involve very much regex or any specialized libraries from node or elsewhere suited to the problem.

Finally, for the benefit of future googlers who might have a similar problem, I've published my solution at https://gist.github.com/2590689 and copied below:

//clothe a hub file that has 'naked' expressions
//e.g. turn {key:$('body p')} into {key:"$('body p')"}
function clothe(contents){

closers = /[\}\]\)\/"']/
openers = /[\{\[\(\/"']/
closing = {
    "{": "}",
    "[": "]",
    "(": ")",
    "/": "/",
    '"': '"',
    "'": "'"
}

contents = contents.split("");

var beforeKey = true;
var inKey = false;
var beforeValue = false;
var inValue = false;
var inArray = false;
var delimiterStack = [];

function inDelimited(){
    return delimiterStack.length > 0;
}

function toggleDelimiter(d){
    if(openers.exec(d) && !closers.exec(d)){
        pushDelimiter(d);
    }else if(openers.exec(d) && closers.exec(d)){
        if(topDelimiter()){
            if(topDelimiter()==d){
                popDelimiterIfValid(d);
            }else{
                pushDelimiter(d);
            }
        }else{
            pushDelimiter(d);
        }
    }else if(closers.exec(d)){
        popDelimiterIfValid(d);
    }
}

function topDelimiter(){
    if(delimiterStack.length>=0){
        return delimiterStack[delimiterStack.length-1];
    }else{
        return undefined;
    }
}

function pushDelimiter(d){
    delimiterStack.push(d);
}

function popDelimiterIfValid(d){
    if(delimiterStack.length>0)
        if(closing[delimiterStack[delimiterStack.length-1]]==d)
            delimiterStack.pop(d);
}

function rTrimmedRightBound(rightBound){
    while(rightBound>0){
        if(!/\s/g.exec(contents[--rightBound])){
            return rightBound+1;
        }
    }
}

for(var i=0; i<contents.length; i++){

    function delimiterCheck(c){
        if(c=='"'){
            toggleDelimiter('"');
            contents.splice(i, 0, '\\');
            i++;
        }else if(openers.exec(c) || closers.exec(c)){
            toggleDelimiter(c)
        }
    }

    if(beforeKey){
        if(/[a-zA-Z0-9$_!]/.exec(contents[i])){
            beforeKey = false;
            inKey = true;
        }
    }else if(inKey){
        if(contents[i]==":"){
            inKey = false;
            beforeValue = true;
        }
    }else if(beforeValue){
        if(/[a-zA-Z0-9$_!'"\(\/]/.exec(contents[i])){
            contents.splice(i, 0, '"');
            i++;
            beforeValue = false;
            inValue = true;
            delimiterCheck(contents[i]);
        }else if(/\{/.exec(contents[i])){
            beforeKey = true;
            beforeValue = false;
        }else if(/\[/.exec(contents[i])){
            beforeValue = false;
            inArray = true;
        }
    }else if(inArray && !inValue){
        if(/[a-zA-Z0-9$_!'"\(\/]/.exec(contents[i])){
            contents.splice(i, 0, '"');
            i++;
            beforeValue = false;
            inValue = true;
            delimiterCheck(contents[i]);
        }
    }else if(inValue){
        if(!inDelimited() && /[\},\]]/.exec(contents[i])){
            contents.splice(rTrimmedRightBound(i), 0, '"');
            i++;
            inValue = false;
            if(/\]/.exec(contents[i])){
                inArray = false;
            }
            beforeKey = !inArray;
        }else{
            delimiterCheck(contents[i]);
        }
    }
}

return contents.join("");
}