all files / lib/parsec/ response.js

100% Statements 42/42
100% Branches 2/2
100% Functions 20/20
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 117 118 119 120                                    135130× 104922× 30208×                             304956× 304956×   304956× 304956×         235277×       115198×             8021× 5710×   2311×             177826× 177826×         194932×       42389×                         189758×     175508×        
/*
 * Parsec
 * https://github.com/d-plaindoux/parsec
 *
 * Copyright (c) 2016 Didier Plaindoux
 * Licensed under the LGPL2 license.
 */
 
module.exports = (function () {
    
    'use strict';
    
    var atry = require('../data/try.js');
    
    /**
     * Response basic type
     */
    function Response() {
    }
        
    // Response 'a 'c => unit -> bool
    Response.prototype.isAccepted = function () {
        return this.fold(
            function() { return true;  }, 
            function() { return false; }
        );
    };
    
    // Response 'a 'c => unit -> bool
    Response.prototype.toTry = function () {
        return this.fold(
            function(accept) { 
                return atry.success(accept.value); 
            }, 
            function(reject) { 
                return atry.failure(new Error("parser error at " + reject.offset)) ; 
            }
        );
    };
            
    /**
     * Accept response class
     */
    function Accept(value, input, offset, consumed) {
        this.offset = offset;
        this.consumed = consumed;
 
        this.value = value; 
        this.input = input;
    }
 
    Accept.prototype = new Response();
    
    // Response 'a 'c => (Accept 'a 'c -> 'a) -> (Reject 'a 'c -> 'a) -> 'a        
    Accept.prototype.fold = function (accept) {
        return accept(this);  
    };
        
    // Response 'a 'c => ('a -> 'b) -> Response 'b 'c
    Accept.prototype.map = function (callback) {
        return new Accept(callback(this.value), this.input, this.offset, this.consumed);  
    };
       
    // Response 'a 'c => ('a -> Response 'b 'c) -> Response 'b 'c
    Accept.prototype.flatmap = function (callback) {
        return callback(this.value);  
    };
       
    // Response 'a 'c => ('a -> bool) -> Response 'b 'c
    Accept.prototype.filter = function (predicate) {
        if (predicate(this.value)) {
            return this;
        } else {
            return new Reject(this.offset, false);
        }
    };
       
    /**
     * Reject response class
     */
    function Reject(offset, consumed) {
        this.offset = offset;
        this.consumed = consumed;
    }
 
    Reject.prototype = new Response();
    
    // Response 'a 'c => (Accept 'a 'c -> 'a) -> (Reject 'a 'c -> 'a) -> 'a        
    Reject.prototype.fold = function (_,reject) {
        return reject(this);  
    };
 
    // Response 'a 'c => ('a -> 'b) -> Response 'b 'c
    Reject.prototype.map = function () {
        return this;
    };
    
    // Response 'a 'c => ('a -> Response 'b 'c) -> Response 'b 'c
    Reject.prototype.flatmap = function () {
        return this;
    };
        
    // Response 'a 'c => ('a -> bool) -> Response 'b 'c
    Reject.prototype.filter = function () {
        return new Reject(this.offset, false);
    };
    
     /** 
      * Constructors
      */    
    return {
        accept: function(value,sequence,offset,consumed) {
            return new Accept(value,sequence,offset,consumed);
        },
        reject: function(offset,consumed) {
            return new Reject(offset,consumed);
        }
    };
    
}());