Skip to content
Advertisement

How can I force a user to indicate that they are switching from operator to operator

I’m creating a JS module that serves as a ‘programming language’ This programming language interprets human words and is supposed to translate it into Javascript.

The programming language is going to be strict on grammar, similarly to other programming languages, and that’s what the question here is here to accomplish.

In my programming language, you can write your program many different ways, but to keep mines clean, I like to split it off in chunks for readability. This block of code shown here:

...
add 2 and 2 
multiply by 5
...

Would spew out:

20

It’s working, but if we are trying to be strict on grammar as well, we would have to ask this question:

  1. Multiply what by 5? The result of the previous math equation, or is the user initiating another equation?

And if we were using the result of the previous math equation, the code would need to look something like this:

...
add 2 and 2
then multiply the result by 5
...

Still spewing the same result of:

20

How can I accomplish this goal?

Full Source Code

source.js:

Array.prototype.remove = function(value) {
    for (var i = this.length; i--; )
    {
        if (this[i] === value) {
            this.splice(i, 1);
        }
    }
}

// from https://stackoverflow.com/questions/175739/how-can-i-check-if-a-string-is-a-valid-number
function isNumeric(str) {
  if (typeof str != "string") return false
  return !isNaN(str) && !isNaN(parseFloat(str))
}

function isOperand(token) {
  const ops = ["add", "multiply", "subtract", "divide"]
  if (ops.includes(token)) {
    return true
  }
  return false
}

function interpret(input) {
  const tokens = input.split(' ') // in fancy programming language terms, 
  // this is a lexical analysis step
  // note that we are not supporting things like
  // double spaces, something to think about!
  tokens.remove('n')
  tokens.remove('')

  console.log(tokens)

  let state = 0 // we are keeping the results from our operation here

  for (i = 0; i < tokens.length; i++) {
    const t = tokens[i] // to keep things shorter
    if (!isOperand(t)) {
      throw new Error(`expected operand token, got: ${t}`)  
    }

    // all operators are binary, so these variables will hold the operands
    // they may be two numbers, or a number and the internal state
    let a, b;

    const next = tokens[i + 1]
    if (next == "by") {
      // we should add the next token (hopefully a number!) to the state
      a = state
      b = parseFloat(tokens[i + 2])
      i += 2 // very important! the two tokens we read should be skipped
      // by the loop. they were "consumed".
    } 
    else if (isNumeric(next)) {
      const and = tokens[i + 2] // this should be the "and"
      if (and != "and") {
          throw new Error(`expected "and" token, got: ${and}`)
      }
      a = parseFloat(next)
      b = parseFloat(tokens[i + 3])
      i += 3 // in this case, we are consuming more tokens 
    } else {
      throw new Error(`unexpected token: ${next}`)  
    }

    switch (t) {
      case "add": 
        state = a + b
        break;
      case "multiply":
        state = a * b
        break;
      case "subtract":
        state = a - b
        break;
      case "divide":
        state = a / b
        break;
    }
  }

  return state
}

function out(main) {
  console.log(interpret(main))
}

module.exports = {out}

index.js:

const cjs = require('./source.js')

var main =  `
  add 2 and 2 
  multiply by 5
`

cjs.out(main)

Advertisement

Answer

By the way, you are using the operand and operator words wrong. Operand means what you perform the operation on, the numbers in this case. Operator is the operation defining symbol (+, * etc)

You should define another type of operator, maybe something like ‘transitionOperator’ which is defined by ‘then’ keyword

If you encounter transitionOperator (then) you should check if the state is previously set. If it is not throw an error because you can’t transition from that. Otherwise you are doing a ‘then’ transition operation which means you need to use the result of previous operation (your state variable) as your operand1 and your operand 2 will be the next token.

Example:

add 2 and 2 // sets the state to 4
then multiply the result by 5 // operator1 = state, operator2 = 5, new state = 20
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement