Skip to content

Instantly share code, notes, and snippets.

@janus
Last active May 24, 2018 08:38
Show Gist options
  • Save janus/c1a147f306be9f73f1036baaf1a06a76 to your computer and use it in GitHub Desktop.
Save janus/c1a147f306be9f73f1036baaf1a06a76 to your computer and use it in GitHub Desktop.

Revisions

  1. janus renamed this gist May 24, 2018. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. janus revised this gist May 24, 2018. 2 changed files with 210 additions and 183 deletions.
    183 changes: 0 additions & 183 deletions .js
    Original file line number Diff line number Diff line change
    @@ -1,183 +0,0 @@
    //Built with Proxy ...using it to learn a bit.
    /*
    * Copy right holder Ikjo
    * You are free to enjoy, however give credit to Ikjo
    * examples
    * mathProxy.twofourMultiplyonePlusfivefiveDividethree()
    * mathProxy.two_four_Multiply_one_Plus_five_five_Divide_three()
    * conditions
    * math operators are titlized
    * number are lower case
    * it accepts '_' as separation
    * mathProxy is already instantiated
    */

    'use strict'
    const BINARY_OPS = ["Plus", "Minus", "Divide", "Multiply"];
    const OPS_WEIGHT = {Plus: 1, Minus: 1, Divide: 2, Multiply: 2};
    const FUNCTIONS = {
    Plus: (left, right) => left + right ,
    Minus: (left, right) => left - right ,
    Multiply: (left, right) => left * right ,
    Divide: (left, right) => {
    if(right === 0){
    throw new Error("Division by zero is not allowed");
    }
    return left / right;
    }
    };


    var mathProxy = new Proxy({}, {
    get(target, property){
    return computeMath(property);
    }
    });


    function computeMath(query) {
    let parsed = parser(query);
    return () => interpret(parsed.tokens) ;
    }

    function isUpperCase(str) {
    return str === str.toUpperCase();
    }

    function mapStringToNum(str) {
    let strNumMap = {'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six':'6', 'seven': '7', 'eight': '8', 'nine' : '9', 'zero': '0'};
    return strNumMap[str];
    }

    function parser(nstream) {
    let stream = nstream.replace(/_/g, '');
    let len = stream.length, storeStringNum = [], tokens = [] ,val;

    let unknown = 1, operand = 2, operator = 3;
    let state = unknown, string_acc = '', i = 0;
    while(i < len) {
    switch(state) {
    case unknown:
    state = isUpperCase(stream[i]) ? operator : operand;
    string_acc = stream[i];
    i++;
    break;
    case operand:
    if (i < len) {
    string_acc += stream[i];
    i++;
    while(i < len) {
    if (!mapStringToNum(string_acc)) {
    string_acc += stream[i];
    i++;
    continue;
    } else {
    storeStringNum.push(mapStringToNum(string_acc));
    string_acc = '';
    state = unknown;
    break;
    }
    }
    }
    if (mapStringToNum(string_acc)) {
    storeStringNum.push(mapStringToNum(string_acc));
    } else if(string_acc) {
    throw new Error(`Unknown token operand <${string_acc}>`);
    }
    break;
    case operator:
    if (storeStringNum.length === 0){
    throw new Error("Operator must be binary operator");
    } else {
    val = storeStringNum.join('');
    tokens.push(Number(val));
    storeStringNum = [];
    }
    if (i < len) {
    string_acc += stream[i];
    i++;
    while(i < len){
    if (BINARY_OPS.includes(string_acc)) {
    tokens.push(string_acc);
    string_acc = '';
    state = unknown;
    break;
    }
    string_acc += stream[i];
    i++;
    }
    }
    break;
    default:
    throw new Error(`Unknown token <${string_acc}>`);
    }
    }
    if (storeStringNum.length === 0){
    throw new Error('Only Binary operators are expected');
    } else {
    val = storeStringNum.join('');
    tokens.push(Number(val));
    }
    return { tokens } ;
    }

    function interpret(tokens) {
    let vals = [], ops = [], right, left , val, vop;
    let len = tokens.length, i = 0;
    while( i < len) {
    if(typeof tokens[i] === 'number') {
    vals.push(tokens[i]);
    i++;
    continue;
    }
    if (ops.length === 0) {
    ops.push(tokens[i]);
    i++
    continue;
    } else {
    vop = ops.pop();
    if (OPS_WEIGHT[vop] > OPS_WEIGHT[tokens[i]]) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[vop](left, right));
    while(ops.length > 0){
    vop = ops.pop();
    if (OPS_WEIGHT[vop] > OPS_WEIGHT[tokens[i]]) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[vop](left, right));
    continue;
    }
    ops.push(vop);
    ops.push(tokens[i]);
    break;
    }
    if(ops.length === 0){
    ops.push(tokens[i]);

    }
    } else {
    ops.push(vop);
    ops.push(tokens[i]);
    }
    i++;
    }
    }
    while(ops.length > 0){
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[ops.pop()](left, right));
    }

    if(vals.length === 1) {
    return vals.pop();
    } else {
    throw new Error("Interpretation failed, wrong grammar");
    }

    }
    //console.log(parser("twotwoPluseightfive"));
    //console.log(interpret(parser("twotwoPluseightfiveMultiplyfour").tokens));
    console.log(mathProxy.twofourMultiplyonePlusfivefiveDividethree());
    console.log(mathProxy.two_four_Multiply_one_Plus_five_five_Divide_three());
    210 changes: 210 additions & 0 deletions mathProxy
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,210 @@
    // This is just a sample script. Paste your real code (javascript or HTML) here.
    /*
    * Copy right holder Ikjo
    * You are free to enjoy, however give credit to Ikjo
    * examples
    * mathProxy.twofourMultiplyonePlusfivefiveDividethree()
    * mathProxy.two_four_Multiply_one_Plus_five_five_Divide_three()
    * conditions
    * math operators are titlized
    * number are lower case
    * it accepts '_' as separation
    * mathProxy is already instantiated

    */
    'use strict'
    const BINARY_OPS = ["Plus", "Minus", "Divide", "Multiply"];
    const OPS_WEIGHT = {
    Plus: 1,
    Minus: 1,
    Divide: 2,
    Multiply: 2
    };
    const FUNCTIONS = {
    Plus: (left, right) => left + right,
    Minus: (left, right) => left - right,
    Multiply: (left, right) => left * right,
    Divide: (left, right) => {
    if (right === 0) {
    throw new Error("Division by zero is not allowed");
    }
    return left / right;
    }
    };


    var mathProxy = new Proxy({}, {
    get(target, property) {
    return computeMath(property);
    }
    });


    function computeMath(query) {
    let parsed = parser(query);
    return () => interpret(parsed.tokens);
    }

    function isUpperCase(str) {
    return str === str.toUpperCase();
    }

    function mapStringToNum(str) {
    let strNumMap = {
    'one': '1',
    'two': '2',
    'three': '3',
    'four': '4',
    'five': '5',
    'six': '6',
    'seven': '7',
    'eight': '8',
    'nine': '9',
    'zero': '0'
    };
    return strNumMap[str];
    }

    function parser(nstream) {
    let stream = nstream.replace(/_/g, '');
    let len = stream.length,
    storeStringNum = [],
    tokens = [],
    val;

    let unknown = 1,
    operand = 2,
    operator = 3;
    let state = unknown,
    string_acc = '',
    i = 0;
    while (i < len) {
    switch (state) {
    case unknown:
    state = isUpperCase(stream[i]) ? operator : operand;
    string_acc = stream[i];
    i++;
    break;
    case operand:
    if (i < len) {
    string_acc += stream[i];
    i++;
    while (i < len) {
    if (!mapStringToNum(string_acc)) {
    string_acc += stream[i];
    i++;
    continue;
    } else {
    storeStringNum.push(mapStringToNum(string_acc));
    string_acc = '';
    state = unknown;
    break;
    }
    }
    }
    if (mapStringToNum(string_acc)) {
    storeStringNum.push(mapStringToNum(string_acc));
    } else if (string_acc) {
    throw new Error(`Unknown token operand <${string_acc}>`);
    }
    break;
    case operator:
    if (storeStringNum.length === 0) {
    throw new Error("Operator must be binary operator");
    } else {
    val = storeStringNum.join('');
    tokens.push(Number(val));
    storeStringNum = [];
    }
    if (i < len) {
    string_acc += stream[i];
    i++;
    while (i < len) {
    if (BINARY_OPS.includes(string_acc)) {
    tokens.push(string_acc);
    string_acc = '';
    state = unknown;
    break;
    }
    string_acc += stream[i];
    i++;
    }
    }
    break;
    default:
    throw new Error(`Unknown token <${string_acc}>`);
    }
    }
    if (storeStringNum.length === 0) {
    throw new Error('Only Binary operators are expected');
    } else {
    val = storeStringNum.join('');
    tokens.push(Number(val));
    }
    return {
    tokens
    };
    }

    function interpret(tokens) {
    let vals = [],
    ops = [],
    right, left, val, vop;
    let len = tokens.length,
    i = 0;
    while (i < len) {
    if (typeof tokens[i] === 'number') {
    vals.push(tokens[i]);
    i++;
    continue;
    }
    if (ops.length === 0) {
    ops.push(tokens[i]);
    i++
    continue;
    } else {
    vop = ops.pop();
    if (OPS_WEIGHT[vop] > OPS_WEIGHT[tokens[i]]) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[vop](left, right));
    while (ops.length > 0) {
    vop = ops.pop();
    if (OPS_WEIGHT[vop] > OPS_WEIGHT[tokens[i]]) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[vop](left, right));
    continue;
    }
    ops.push(vop);
    ops.push(tokens[i]);
    break;
    }
    if (ops.length === 0) {
    ops.push(tokens[i]);

    }
    } else {
    ops.push(vop);
    ops.push(tokens[i]);
    }
    i++;
    }
    }
    while (ops.length > 0) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[ops.pop()](left, right));
    }

    if (vals.length === 1) {
    return vals.pop();
    } else {
    throw new Error("Interpretation failed, wrong grammar");
    }

    }
    //console.log(parser("twotwoPluseightfive"));
    //console.log(interpret(parser("twotwoPluseightfiveMultiplyfour").tokens));
    console.log(mathProxy.twofourMultiplyonePlusfivefiveDividethree());
    console.log(mathProxy.two_four_Multiply_one_Plus_five_five_Divide_three());
  3. janus created this gist May 24, 2018.
    183 changes: 183 additions & 0 deletions .js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,183 @@
    //Built with Proxy ...using it to learn a bit.
    /*
    * Copy right holder Ikjo
    * You are free to enjoy, however give credit to Ikjo
    * examples
    * mathProxy.twofourMultiplyonePlusfivefiveDividethree()
    * mathProxy.two_four_Multiply_one_Plus_five_five_Divide_three()
    * conditions
    * math operators are titlized
    * number are lower case
    * it accepts '_' as separation
    * mathProxy is already instantiated
    */

    'use strict'
    const BINARY_OPS = ["Plus", "Minus", "Divide", "Multiply"];
    const OPS_WEIGHT = {Plus: 1, Minus: 1, Divide: 2, Multiply: 2};
    const FUNCTIONS = {
    Plus: (left, right) => left + right ,
    Minus: (left, right) => left - right ,
    Multiply: (left, right) => left * right ,
    Divide: (left, right) => {
    if(right === 0){
    throw new Error("Division by zero is not allowed");
    }
    return left / right;
    }
    };


    var mathProxy = new Proxy({}, {
    get(target, property){
    return computeMath(property);
    }
    });


    function computeMath(query) {
    let parsed = parser(query);
    return () => interpret(parsed.tokens) ;
    }

    function isUpperCase(str) {
    return str === str.toUpperCase();
    }

    function mapStringToNum(str) {
    let strNumMap = {'one': '1', 'two': '2', 'three': '3', 'four': '4', 'five': '5', 'six':'6', 'seven': '7', 'eight': '8', 'nine' : '9', 'zero': '0'};
    return strNumMap[str];
    }

    function parser(nstream) {
    let stream = nstream.replace(/_/g, '');
    let len = stream.length, storeStringNum = [], tokens = [] ,val;

    let unknown = 1, operand = 2, operator = 3;
    let state = unknown, string_acc = '', i = 0;
    while(i < len) {
    switch(state) {
    case unknown:
    state = isUpperCase(stream[i]) ? operator : operand;
    string_acc = stream[i];
    i++;
    break;
    case operand:
    if (i < len) {
    string_acc += stream[i];
    i++;
    while(i < len) {
    if (!mapStringToNum(string_acc)) {
    string_acc += stream[i];
    i++;
    continue;
    } else {
    storeStringNum.push(mapStringToNum(string_acc));
    string_acc = '';
    state = unknown;
    break;
    }
    }
    }
    if (mapStringToNum(string_acc)) {
    storeStringNum.push(mapStringToNum(string_acc));
    } else if(string_acc) {
    throw new Error(`Unknown token operand <${string_acc}>`);
    }
    break;
    case operator:
    if (storeStringNum.length === 0){
    throw new Error("Operator must be binary operator");
    } else {
    val = storeStringNum.join('');
    tokens.push(Number(val));
    storeStringNum = [];
    }
    if (i < len) {
    string_acc += stream[i];
    i++;
    while(i < len){
    if (BINARY_OPS.includes(string_acc)) {
    tokens.push(string_acc);
    string_acc = '';
    state = unknown;
    break;
    }
    string_acc += stream[i];
    i++;
    }
    }
    break;
    default:
    throw new Error(`Unknown token <${string_acc}>`);
    }
    }
    if (storeStringNum.length === 0){
    throw new Error('Only Binary operators are expected');
    } else {
    val = storeStringNum.join('');
    tokens.push(Number(val));
    }
    return { tokens } ;
    }

    function interpret(tokens) {
    let vals = [], ops = [], right, left , val, vop;
    let len = tokens.length, i = 0;
    while( i < len) {
    if(typeof tokens[i] === 'number') {
    vals.push(tokens[i]);
    i++;
    continue;
    }
    if (ops.length === 0) {
    ops.push(tokens[i]);
    i++
    continue;
    } else {
    vop = ops.pop();
    if (OPS_WEIGHT[vop] > OPS_WEIGHT[tokens[i]]) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[vop](left, right));
    while(ops.length > 0){
    vop = ops.pop();
    if (OPS_WEIGHT[vop] > OPS_WEIGHT[tokens[i]]) {
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[vop](left, right));
    continue;
    }
    ops.push(vop);
    ops.push(tokens[i]);
    break;
    }
    if(ops.length === 0){
    ops.push(tokens[i]);

    }
    } else {
    ops.push(vop);
    ops.push(tokens[i]);
    }
    i++;
    }
    }
    while(ops.length > 0){
    right = vals.pop();
    left = vals.pop();
    vals.push(FUNCTIONS[ops.pop()](left, right));
    }

    if(vals.length === 1) {
    return vals.pop();
    } else {
    throw new Error("Interpretation failed, wrong grammar");
    }

    }
    //console.log(parser("twotwoPluseightfive"));
    //console.log(interpret(parser("twotwoPluseightfiveMultiplyfour").tokens));
    console.log(mathProxy.twofourMultiplyonePlusfivefiveDividethree());
    console.log(mathProxy.two_four_Multiply_one_Plus_five_five_Divide_three());