Class: Dhaka::Evaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/evaluator/evaluator.rb

Overview

Abstract base class for evaluators.

Defining an evaluator is an easy way to perform syntax-directed evaluation without having to generate an abstract syntax tree representation of the input.

An evaluation rule for a given production named bar is defined by calling for_bar with a block that performs the evaluation. For detailed examples, see the evaluators in the test suite.

The following is an evaluator for arithmetic expressions. When a parse tree node is encountered that corresponds to the production named addition, the block passed to for_addition is invoked. The evaluate method is then recursively called on the child nodes, in this case the operands to the addition operation. The result is obtained by adding the evaluation results of the child nodes.

class ArithmeticPrecedenceEvaluator < Dhaka::Evaluator

  self.grammar = ArithmeticPrecedenceGrammar

  define_evaluation_rules do

    for_subtraction do 
      evaluate(child_nodes[0]) - evaluate(child_nodes[2])
    end

    for_addition do
      evaluate(child_nodes[0]) + evaluate(child_nodes[2])
    end

    for_division do
      evaluate(child_nodes[0]).to_f/evaluate(child_nodes[2]) 
    end

    for_multiplication do
      evaluate(child_nodes[0]) * evaluate(child_nodes[2])
    end

    for_literal do
      child_nodes[0].token.value.to_i
    end

    for_parenthetized_expression do
      evaluate(child_nodes[1])
    end

    for_negated_expression do
      -evaluate(child_nodes[1])
    end

    for_power do
      evaluate(child_nodes[0])**evaluate(child_nodes[2])
    end

  end

end

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.define_evaluation_rulesObject

Defining evaluation rules within a block passed to this method tells the evaluator to carry out a rudimentary check of your definitions and define default evaluation rules for pass-through productions (i.e. productions with expansions consisting of exactly one grammar symbol). The default evaluation rule for such productions is to simply return the result of calling evaluate on the unique child node. If you neglect to define a rule for a non-pass-through production (one where the expansion consists of multiple symbols), the evaluator will raise an exception at loading time, listing all the productions that absolutely need to be defined before you can continue.



68
69
70
71
# File 'lib/evaluator/evaluator.rb', line 68

def define_evaluation_rules
  yield
  check_definitions
end

Instance Method Details

#child_nodesObject

Returns the array of child nodes of the node being evaluated currently.



117
118
119
# File 'lib/evaluator/evaluator.rb', line 117

def child_nodes
  @node_stack.last
end

#evaluate(node) ⇒ Object

Evaluate a parse tree node.



108
109
110
111
112
113
114
# File 'lib/evaluator/evaluator.rb', line 108

def evaluate node
  @node_stack ||= []
  @node_stack << node.child_nodes
  result      = send(node.production.name)
  @node_stack.pop
  result
end