Sha256: 5e707d3dfdf77c25468b458cddb1e62e32627aeb2821b3f9d33b27b284972d05

Contents?: true

Size: 1.61 KB

Versions: 2

Compression:

Stored size: 1.61 KB

Contents

require 'citrus/sugar'

# A grammar for mathematical formulas that apply the basic four operations to
# non-negative numbers (integers and floats), respecting operator precedence and
# ignoring whitespace.
Calc = Citrus::Grammar.new {
  rule term do
    any(additive, factor)
  end

  rule additive do
    all(factor, label(additive_op, operator), term) {
      def value
        operator.apply(factor.value, term.value)
      end
    }
  end

  rule factor do
    any(multiplicative, primary)
  end

  rule multiplicative do
    all(primary, label(multiplicative_op, operator), factor) {
      def value
        operator.apply(primary.value, factor.value)
      end
    }
  end

  rule primary do
    any(term_paren, number)
  end

  rule term_paren do
    all(lparen, term, rparen) {
      def value
        term.value
      end
    }
  end

  rule additive_op do
    any(plus, minus) {
      def apply(factor, term)
        text.strip == '+' ? factor + term : factor - term
      end
    }
  end

  rule multiplicative_op do
    any(star, slash) {
      def apply(primary, factor)
        text.strip == '*' ? primary * factor : primary / factor
      end
    }
  end

  rule number do
    any(float, integer)
  end

  rule float do
    all(/[0-9]+/, '.', /[0-9]+/, space) {
      def value
        text.strip.to_f
      end
    }
  end

  rule integer do
    all(/[0-9]+/, space) {
      def value
        text.strip.to_i
      end
    }
  end

  rule lparen, ['(', space]
  rule rparen, [')', space]
  rule plus,   ['+', space]
  rule minus,  ['-', space]
  rule star,   ['*', space]
  rule slash,  ['/', space]

  rule space,  /[ \t\n\r]*/
}

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
citrus-1.4.0 examples/calc_sugar.rb
citrus-1.3.0 examples/calc_sugar.rb