Ruby simple interactive interpreter – Code Review Stack Exchange

This is my first Ruby code and a solution to this problem https://www.codewars.com/kata/53005a7b26d12be55c000243/train/ruby The task is to make a simple interpreter that will take expressions and calculate the results. I’m just looking for general feedback on following Ruby standard practices and ways I could shorten the code by omitting parentheses for example


  def input expr
    if expr.strip == ""
      return ""
    end
    # puts expr
    tokens = tokenize(expr).map{ |a| a(0) }    
    parsedTokens = parseTokens tokens
    if parsedTokens.length == 1
      if !@variables.key? parsedTokens(0).name
        raise 'unitialized variable'
      end
      return @variables(parsedTokens(0).name)
    end
    # todo can the user enter just a number?
    leastPrecedentNode = partition parsedTokens
    rootOfBuiltTree = buildTree leastPrecedentNode
    result = calculateRecursive rootOfBuiltTree
    result
  end

  private

  class OperatorInfo
      @@operators = { '=' => 0, '+' => 1, '-' => 1, '*' => 2, '/' => 2, '%' => 2 }
      @@assignmentOperator = '='

      def self.operators
        @@operators
      end

      def self.assignmentOperator
        @@assignmentOperator
      end
  end

  class ParseUnit
    attr_reader :overallIndex
    attr_reader :nestLevel
    attr_reader :indexInLevel

    def initialize(overallIndex, nestLevelArg, indexInLevelArg)
      @overallIndex = overallIndex
      @nestLevel = nestLevelArg
      @indexInLevel = indexInLevelArg
    end
  end

  class ConstantParse < ParseUnit
    attr_reader :value

    def initialize(value, overallIndex, nestLevel, indexInLevel)
      super(overallIndex, nestLevel, indexInLevel)
      @value = value
    end
  end

  class OperatorParse < ParseUnit
    attr_reader :operator
    attr_reader :priority

    def initialize(operator, overallIndex, nestLevel, indexInLevel)
      super(overallIndex, nestLevel, indexInLevel)
      @operator = operator
      @priority = OperatorInfo.operators(operator)
    end
  end

  class VariableParse < ParseUnit
    attr_reader :name

    def initialize(name, overallIndex, nestLevel, indexInLevel)
      super(overallIndex, nestLevel, indexInLevel)
      @name = name
    end
  end

  def parseTokens (tokens)
    ret = ()
    nestLevel = 0
    indexes = (0)
    overallIndex = 0
    tokens.each do | t | 
      # can be operator, constant number, paren, variable 
      # puts "curToken is #{t}"

      case t       
      #operator
      when OperatorInfo.operators.keys.include?(t).to_s == 'true' ? t : ''
        ret.push OperatorParse.new t, overallIndex, nestLevel, indexes(nestLevel)
          overallIndex += 1
          indexes(nestLevel) += 1 
      # is a constant number
      when /Ad+z/        
        ret.push ConstantParse.new t.to_i, overallIndex, nestLevel, indexes(nestLevel)
        overallIndex += 1
        indexes(nestLevel) += 1
      when '('
        nestLevel += 1
        if indexes.length <= nestLevel
          indexes.push(0)
        end
      when ')'
        nestLevel -= 1
      #variable
      when String
        ret.push VariableParse.new t, overallIndex, nestLevel, indexes(nestLevel)
        overallIndex += 1
        indexes(nestLevel) += 1
      else
        puts "error in parse tokens with token #{t}"
      end
    end
    ret
  end

  class OperatorNode
    attr_reader :operator
    attr_reader :left
    attr_reader :right

    def initialize(operator, left, right)
      @left = left
      @right = right
      @operator = operator
      @priority = OperatorInfo.operators(operator) 
    end
  end

  def partition(parsedTokens)
    opTokens = parsedTokens.select { |token| token.is_a?(OperatorParse) }
    op = leastPrecedentOp opTokens
    left = parsedTokens.select { |x| x.overallIndex < op.overallIndex }
    right = parsedTokens.select { |x| x.overallIndex > op.overallIndex }
    OperatorNode.new op, left, right
  end

  def leastPrecedentOp opTokens
    if opTokens.length == 1 
      return opTokens(0)
    end
    # todo dry out this sort with the next one
    sortedByNestLevel = opTokens.sort_by { |x| x.nestLevel }
    nestLevelTies = sortedByNestLevel.select { |x| x.nestLevel == sortedByNestLevel(0).nestLevel }
    if nestLevelTies.length == 1
      return nestLevelTies(0)
    end
    sortedByPriority = nestLevelTies.sort_by { |x| x.priority }
    priorityTies = sortedByPriority.select { |x| x.priority == sortedByPriority(0).priority }
    if priorityTies.length == 1
      return priorityTies(0)
    end
    sortedByIndexInLevel = priorityTies.sort_by { |x| x.indexInLevel * -1 }
    sortedByIndexInLevel(0)
  end

  def buildTree(opNode)
    # puts opNode
    # base case
    leftIsSingle = opNode.left.length == 1
    rightIsSingle = opNode.right.length == 1
    if leftIsSingle && rightIsSingle
      return OperatorNode.new opNode.operator.operator, opNode.left, opNode.right   
    end
    # recursive call
    leftRet = nil
    if leftIsSingle
      leftRet = opNode.left(0)
    else
      leftPart = partition opNode.left
      leftRet = buildTree leftPart
    end

    rightRet = nil
    if rightIsSingle
      rightRet = opNode.right(0)
    else
      rightPart = partition opNode.right
      rightRet = buildTree rightPart
    end

    # combine and return
    OperatorNode.new opNode.operator.operator, leftRet, rightRet
  end

  def calculateRecursive node
    # base case
    if isLeaf? node, nil
      return getValue node
    end    
    leftIsLeaf = isLeaf? node, node.left
    rightIsLeaf = isLeaf? node, node.right
    if leftIsLeaf && rightIsLeaf
      if node.operator == OperatorInfo.assignmentOperator
        return calculateImpl node.operator, node.left(0).name, (getValue node.right)
      end
      leftVal = getValue node.left
      rightVal = getValue node.right
      return calculateImpl node.operator, leftVal, rightVal
    end
    # recursive call
    leftResult = nil
    if leftIsLeaf && node.operator != OperatorInfo.assignmentOperator
      leftResult = getValue node.left
    elsif leftIsLeaf && node.operator
      leftResult = node.left.name
    else
      leftResult = calculateRecursive node.left
    end
    rightResult = nil
    if rightIsLeaf
      rightResult = getValue node.right
    else
      rightResult = calculateRecursive node.right
    end
    # combine and return
    result = calculateImpl node.operator, leftResult, rightResult
    result
  end

  def isLeaf?(parent, node)
    # if parent
    isConstant = node.is_a? ConstantParse 
    if node.is_a? Array 
      isConstant = node(0).is_a? ConstantParse
    end
    isVariable = node.is_a? VariableParse
    if node.is_a? Array 
      isVariable = node(0).is_a? VariableParse
    end
    return isConstant || isVariable
  end

  def getValue node
    nodeVal = nil
    if node.is_a? Array
      nodeVal = node(0)
    else
      nodeVal = node
    end
    if nodeVal.is_a? ConstantParse
      return nodeVal.value
    end
    if nodeVal.is_a? VariableParse
      if @variables.key? nodeVal.name
        return @variables(nodeVal.name)
      end
      return nodeVal.name
    end
  end

  def calculateImpl(operator, left, right)
    #puts "#{left} #{operator} #{right}"
    case operator
    when '+'
      return left + right
    when '-'
      return left - right
    when '/'
      return left.to_f / right
    when '*'
      return left * right
    when '%'
      return left % right
    when '='
      @variables(left) = right
      return right
    end
  end

  def initialize
    @variables = {}
  end  

  def tokenize program
    return () if program == ''
    regex = /s*((-+*/%=())|(A-Za-z_)(A-Za-z0-9_)*|(0-9)*.?(0-9)+)s*/
    program.scan(regex).select { |s| !(s =~ /^s*$/) }
  end
end

Interactive workflow tool – User Experience Stack Exchange

I'm interested in creating an interactive workflow tool like this New York Times (NYT) website.

My team members clicked the "Yes" or "No" buttons in the workflow tool and displayed interactive messages similar to the buttons on the NYT website. I've heard of online tools like Survey Monkey, but they can't achieve this kind of interactivity. I'm not a web designer and I don't know the coding for it. Therefore I want to use an online platform / tool to do this. Can anyone recommend an online platform or tool that is easy to use and can create such a workflow?

integrity – How do you securely give access to a Java App interactive console (Linux/GNU)?

I have a Java App running, which prints out messages into STDOUT and also has an active interactive console (also accepts STDIN), when the server has started up.

How do I securely give access to an external person (outside the network) to the console and nothing else?

I was figuring using ncat --ssl -e java filenamehere

And setting a firewall rule for the port used to only allow packets from one origin:

iptables -I INPUT ! --src 1.2.3.4 -m tcp -p tcp --dport 777 -j DROP # if it's not 1.2.3.4, drop it

But is that secure?

In theory, IP spoofing can be used or are modern mitigation methods built into the OS? I tried setting nospoof on in the host.conf file but it seems that it’s obsolete.

I was thinking of giving reverse-shell but that probably is a bit too much and insecure in my opinion. What is your opinion?

GUI design – Live / interactive elements in tab bars of the browser

I recently saw another interesting example of an interactive / live UI element in the tab bars of the browser. This time it is a% scrolled value for one page.

Enter the image description here

A very popular and common example I saw earlier was the number of unread emails displayed for email applications running in a browser (e.g. Gmail).

Enter the image description here

Is there a term for this type of UI element that was developed specifically for the Browser tab? The term favicon was used specifically for browser tabs, so I wonder if this applies to UI elements of this type as well.

I need a script for interactive tables

Hi Guys,
SEMrush

I need a script with which I can create interactive tables, similar to Tab, but less "completely", because I only have to create tables with a maximum of two / three columns and an adjustment of almost zero (only numerical values). For interactive, I mean that users can sort the data.

The source of the data would probably be a CSV file, which is not important, by the way. Once the spreadsheet is set for publication, I really don't care if the output is an iframe or an iframe

web analytics