all files / lib/genlex/ genlex.js

100% Statements 42/42
50% Branches 1/2
100% Functions 22/22
100% Lines 42/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                            17× 17× 17× 17× 17×       38×   151×         38× 38×       40×       38× 20688×         26× 5716×         25× 10×         25× 543×         25× 4083×         25×         23×               18×                 17×     38×          
/*
 * Parsec
 * https://github.com/d-plaindoux/parsec
 *
 * Copyright (c) 2016 Didier Plaindoux
 * Licensed under the LGPL2 license.
 */
 
module.exports = (function () {
    
    'use strict';
    
    var parser = require('../parsec/parser.js'),
        unit = require('../data/unit.js');
    
    // (string -> 'a,string -> 'a,number -> 'a,string -> 'a,char -> 'a) -> GenlexFactory 'a
    function GenlexFactory(keyword, ident, number, string, char) {
        this.keyword = keyword;
        this.ident = ident;
        this.number = number;
        this.string = string;
        this.char = char;
    }
    
    // [String] -> Genlex
    function Genlex(keywords) {
        this.keywordParser = (keywords || []).reduce(
            function(p,s) { 
                return parser.string(s).or(p);
            }, 
            parser.error
        );
        
        var idletter = parser.letter.or(parser.char('_')).or(parser.digit);
        this.identParser = parser.letter.then(idletter.optrep());
    }
    
    // unit -> Parser char char
    Genlex.prototype.space = function() {
        return parser.charIn(" \r\n\f\t");
    };
    
    // unit -> Parser unit char
    Genlex.prototype.spaces = function() {
        return this.space().optrep().map(function() {           
            return unit;
        });
    };
 
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.keyword = function (f) {        
        return this.keywordParser.map(function (s) {
            return f.keyword(s); 
        });
    };
    
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.ident = function (f) {
        return this.identParser.map(function(r) {
            return f.ident([r[0]].concat(r[1]).join('')); 
        });
    };
    
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.number = function (f) {
        return parser.numberLiteral.map(function(s) {
            return f.number(s); 
        });
    };
    
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.string = function (f) {
        return parser.stringLiteral.map(function(s) {
            return f.string(s); 
        });
    };
    
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.char = function (f) {
        return parser.charLiteral.map(function(s) {
            return f.char(s); 
        });
    };
    
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.token = function (f) {
        return this.keyword(f).
                or(this.ident(f)).
                or(this.number(f)).
                or(this.string(f)).
                or(this.char(f));
    };
    
    // GenLexFactory 'a -> Parser 'a char
    Genlex.prototype.tokenBetweenSpaces = function (f) {
        return this.spaces().
                thenRight(this.token(f)).
                thenLeft(this.spaces());
    };
    
    // GenLexFactory 'a -> Parser ['a] char
    Genlex.prototype.tokens = function (f) {
        return this.tokenBetweenSpaces(f).optrep().thenLeft(parser.eos);
    };
    
    return {
        factory: function(keyword, ident, number, string, char) {
            return new GenlexFactory(keyword, ident, number, string, char);
        },
        generator: function(keywords) {
            return new Genlex(keywords);
        }
    };
    
}());