Sha256: 473dca06688d53c37e344bfb51e17f68abff91ff204d356342cbf9f2e70a698c

Contents?: true

Size: 1.74 KB

Versions: 4

Compression:

Stored size: 1.74 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 {
  module FirstValue
    def value
      first.value
    end
  end

  rule term do
    ext(any(additive, factor), FirstValue)
  end

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

  rule factor do
    ext(any(multiplicative, primary), FirstValue)
  end

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

  rule primary do
    ext(any(term_paren, number), FirstValue)
  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
    ext(any(float, integer), FirstValue)
  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

4 entries across 4 versions & 1 rubygems

Version Path
citrus-1.2.2 examples/calc_sugar.rb
citrus-1.2.1 examples/calc_sugar.rb
citrus-1.2.0 examples/calc_sugar.rb
citrus-1.1.0 examples/calc_sugar.rb