Akrantiain2 parser js (beta)

akrantiain2 by la. sozysozbot.

snoj:

parsed:

	

PEG.js

Sentences = xs:(Sentence / Comment / Space)* {
    var ret = {
        define: {},
        conversions: [],
        option: {}
    };
    xs.forEach(function(x) {
        if (x === null ) return;
        if (x.define)
            ret.define[x.define.id] = x.define.values;
        if (x.conversion)
            ret.conversions.push(x.conversion);
        if (x.option)
            ret.option[x.option] = true;
    });
    return ret;
}

Sentence = sent:(Conversion / Define / AtSignOption) _ ';'? { return sent; }

Comment = '#' [^\n]* '\n'? { return null; }
Space = [ \t\r\n\f\v] { return null; }

String = '"' chars:([^\\"\n] / EscapeSequence)* '"' { return chars.join(''); }
Slash = '/' chars:([^\\/\n] / EscapeSequence)* '/' { return chars.join(''); }
EscapeSequence = '\\' char:('\\' / '"' / '/' / "'") { return char; }

Identifier = $([A-Za-z] [A-Za-z0-9_]*)

Define = id:Identifier _ '=' _ values:StringsSepByPipe {
    return { define: {
        id: id,
        values: values.map(function(x) { return x.join(""); })
    }};
}

Select
    = '^' { return { bound: true }; }
    / id:Identifier { return { id: id }; }
    / Strings
    / '(' xs:StringsSepByPipe ')' {
        return { or: xs.map(function(x) { return x.join(""); }) };
    }
Strings = head:String tail:(_ String)* {
    return [head].concat(tail.map(function(x) { return x[1]; }));
}
StringsSepByPipe = head:Strings tail:(_ '|' _ Strings)* {
    return [head].concat(tail.map(function(x) { return x[3]; }));
}

Conversion = lcond:NegSelect? _ selects:Selects _ rcond:NegSelect? _
        '->' _ phonemes:Phonemes {
    if (lcond != null) { selects.unshift(lcond); }
    if (rcond != null) { selects.push(rcond); }
    return { conversion: {
        selects: selects,
        phonemes: phonemes
    }};
}
NegSelect = '!' _ select:Select { return { not: select }; }
Selects = head:Select tail:(_ Select)* {
    var xs = [head].concat(tail.map(function(x) { return x[1]; }));
    var ret= [];
    xs.forEach(function(x) {
        if (Array.isArray(x))
            ret = ret.concat(x);
        else
            ret.push(x);
    });
    return ret;
}

Phonemes = head:Phoneme tail:(_ Phoneme)* {
    return [head].concat(tail.map(function(x) { return x[1]; }));
}
Phoneme = '$' { return null; } / Slash

AtSignOption = '@' _ id:Identifier {
    return { option: id };
}

_ = [ \t\r\f\v]*