# Autogenerated from a Treetop grammar. Edits may be lost.


# Copyright 2013 Smartling, Inc.
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#    http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#!/usr/bin/ruby
require 'rubygems'
require 'treetop'

module PluralRules
  include Treetop::Runtime

  def root
    @root ||= :condition
  end

  module Condition0
    def ws1
      elements[0]
    end

    def ws2
      elements[2]
    end

    def a
      elements[3]
    end
  end

  module Condition1
    def h
      elements[0]
    end

    def t
      elements[1]
    end
  end

  module Condition2
    def value
      b = t.elements.map{|x| x.a.value}
      return [h.value, *b].map{|x| '(' + x + ')'}.join(' || ') if b.size > 0
      h.value
    end
  end

  def _nt_condition
    start_index = index
    if node_cache[:condition].has_key?(index)
      cached = node_cache[:condition][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    r1 = _nt_and_condition
    s0 << r1
    if r1
      s2, i2 = [], index
      loop do
        i3, s3 = index, []
        r4 = _nt_ws
        s3 << r4
        if r4
          if has_terminal?('or', false, index)
            r5 = instantiate_node(SyntaxNode,input, index...(index + 2))
            @index += 2
          else
            terminal_parse_failure('or')
            r5 = nil
          end
          s3 << r5
          if r5
            r6 = _nt_ws
            s3 << r6
            if r6
              r7 = _nt_and_condition
              s3 << r7
            end
          end
        end
        if s3.last
          r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
          r3.extend(Condition0)
        else
          @index = i3
          r3 = nil
        end
        if r3
          s2 << r3
        else
          break
        end
      end
      r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
      s0 << r2
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(Condition1)
      r0.extend(Condition2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:condition][start_index] = r0

    r0
  end

  module AndCondition0
    def ws1
      elements[0]
    end

    def ws2
      elements[2]
    end

    def a
      elements[3]
    end
  end

  module AndCondition1
    def h
      elements[0]
    end

    def t
      elements[1]
    end
  end

  module AndCondition2
    def value
      b = t.elements.map{|x| x.a.value}
      return [h.value, *b].map{|x| '(' + x + ')'}.join(' && ') if b.size > 0
      h.value
    end
  end

  def _nt_and_condition
    start_index = index
    if node_cache[:and_condition].has_key?(index)
      cached = node_cache[:and_condition][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    r1 = _nt_relation
    s0 << r1
    if r1
      s2, i2 = [], index
      loop do
        i3, s3 = index, []
        r4 = _nt_ws
        s3 << r4
        if r4
          if has_terminal?('and', false, index)
            r5 = instantiate_node(SyntaxNode,input, index...(index + 3))
            @index += 3
          else
            terminal_parse_failure('and')
            r5 = nil
          end
          s3 << r5
          if r5
            r6 = _nt_ws
            s3 << r6
            if r6
              r7 = _nt_relation
              s3 << r7
            end
          end
        end
        if s3.last
          r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
          r3.extend(AndCondition0)
        else
          @index = i3
          r3 = nil
        end
        if r3
          s2 << r3
        else
          break
        end
      end
      r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
      s0 << r2
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(AndCondition1)
      r0.extend(AndCondition2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:and_condition][start_index] = r0

    r0
  end

  module Relation0
    def value
      text_value if terminal?
      elements[0].value if nonterminal?
    end
  end

  def _nt_relation
    start_index = index
    if node_cache[:relation].has_key?(index)
      cached = node_cache[:relation][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0 = index
    r1 = _nt_is_relation
    if r1
      r0 = r1
    else
      r2 = _nt_in_relation
      if r2
        r0 = r2
      else
        r3 = _nt_within_relation
        if r3
          r0 = r3
        else
          if has_terminal?('n', false, index)
            r4 = instantiate_node(SyntaxNode,input, index...(index + 1))
            r4.extend(Relation0)
            @index += 1
          else
            terminal_parse_failure('n')
            r4 = nil
          end
          if r4
            r0 = r4
          else
            @index = i0
            r0 = nil
          end
        end
      end
    end

    node_cache[:relation][start_index] = r0

    r0
  end

  module IsRelation0
    def ws
      elements[0]
    end

  end

  module IsRelation1
    def expr
      elements[0]
    end

    def ws1
      elements[1]
    end

    def t
      elements[3]
    end

    def ws2
      elements[4]
    end

    def number
      elements[5]
    end
  end

  module IsRelation2
    def value
      e = expr.value
      e = '(' + e + ')' unless e == 'n'
      e + (t.empty? ? ' == ' : ' != ') + number.value
    end
  end

  def _nt_is_relation
    start_index = index
    if node_cache[:is_relation].has_key?(index)
      cached = node_cache[:is_relation][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    r1 = _nt_expr
    s0 << r1
    if r1
      r2 = _nt_ws
      s0 << r2
      if r2
        if has_terminal?('is', false, index)
          r3 = instantiate_node(SyntaxNode,input, index...(index + 2))
          @index += 2
        else
          terminal_parse_failure('is')
          r3 = nil
        end
        s0 << r3
        if r3
          i5, s5 = index, []
          r6 = _nt_ws
          s5 << r6
          if r6
            if has_terminal?('not', false, index)
              r7 = instantiate_node(SyntaxNode,input, index...(index + 3))
              @index += 3
            else
              terminal_parse_failure('not')
              r7 = nil
            end
            s5 << r7
          end
          if s5.last
            r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
            r5.extend(IsRelation0)
          else
            @index = i5
            r5 = nil
          end
          if r5
            r4 = r5
          else
            r4 = instantiate_node(SyntaxNode,input, index...index)
          end
          s0 << r4
          if r4
            r8 = _nt_ws
            s0 << r8
            if r8
              r9 = _nt_number
              s0 << r9
            end
          end
        end
      end
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(IsRelation1)
      r0.extend(IsRelation2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:is_relation][start_index] = r0

    r0
  end

  module InRelation0
    def ws
      elements[0]
    end

  end

  module InRelation1
    def expr
      elements[0]
    end

    def t
      elements[1]
    end

    def ws1
      elements[2]
    end

    def ws2
      elements[4]
    end

    def r
      elements[5]
    end
  end

  module InRelation2
    def value
      e = expr.value
      e = '(' + e + ')' unless e == 'n'
      r.value.map{|v|
        s = if t.empty?
          v.is_a?(Array) ? (e + ' >= ' + v[0] + ' && ' + e + ' <= ' + v[1]) : (e + ' == ' + v)
        else
          v.is_a?(Array) ? (e + ' < ' + v[0] + ' || ' + e + ' > ' + v[1]) : (e + ' != ' + v)
        end
        '(' + s + ')'
      }.join(t.empty? ? ' || ':' && ')
    end
  end

  def _nt_in_relation
    start_index = index
    if node_cache[:in_relation].has_key?(index)
      cached = node_cache[:in_relation][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    r1 = _nt_expr
    s0 << r1
    if r1
      i3, s3 = index, []
      r4 = _nt_ws
      s3 << r4
      if r4
        if has_terminal?('not', false, index)
          r5 = instantiate_node(SyntaxNode,input, index...(index + 3))
          @index += 3
        else
          terminal_parse_failure('not')
          r5 = nil
        end
        s3 << r5
      end
      if s3.last
        r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
        r3.extend(InRelation0)
      else
        @index = i3
        r3 = nil
      end
      if r3
        r2 = r3
      else
        r2 = instantiate_node(SyntaxNode,input, index...index)
      end
      s0 << r2
      if r2
        r6 = _nt_ws
        s0 << r6
        if r6
          if has_terminal?('in', false, index)
            r7 = instantiate_node(SyntaxNode,input, index...(index + 2))
            @index += 2
          else
            terminal_parse_failure('in')
            r7 = nil
          end
          s0 << r7
          if r7
            r8 = _nt_ws
            s0 << r8
            if r8
              r9 = _nt_range_list
              s0 << r9
            end
          end
        end
      end
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(InRelation1)
      r0.extend(InRelation2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:in_relation][start_index] = r0

    r0
  end

  module WithinRelation0
    def ws
      elements[0]
    end

  end

  module WithinRelation1
    def expr
      elements[0]
    end

    def t
      elements[1]
    end

    def ws1
      elements[2]
    end

    def ws2
      elements[4]
    end

    def r
      elements[5]
    end
  end

  module WithinRelation2
    def value
      e = expr.value
      e = '(' + e + ')' unless e == 'n'
      r.value.map{|v|
        s = if t.empty?
          v.is_a?(Array) ? (e + ' >= ' + v[0] + ' && ' + e + ' <= ' + v[1]) : (e + ' == ' + v)
        else
          v.is_a?(Array) ? (e + ' < ' + v[0] + ' || ' + e + ' > ' + v[1]) : (e + ' != ' + v)
        end
        '(' + s + ')'
      }.join(t.empty? ? ' || ':' && ')
    end
  end

  def _nt_within_relation
    start_index = index
    if node_cache[:within_relation].has_key?(index)
      cached = node_cache[:within_relation][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    r1 = _nt_expr
    s0 << r1
    if r1
      i3, s3 = index, []
      r4 = _nt_ws
      s3 << r4
      if r4
        if has_terminal?('not', false, index)
          r5 = instantiate_node(SyntaxNode,input, index...(index + 3))
          @index += 3
        else
          terminal_parse_failure('not')
          r5 = nil
        end
        s3 << r5
      end
      if s3.last
        r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
        r3.extend(WithinRelation0)
      else
        @index = i3
        r3 = nil
      end
      if r3
        r2 = r3
      else
        r2 = instantiate_node(SyntaxNode,input, index...index)
      end
      s0 << r2
      if r2
        r6 = _nt_ws
        s0 << r6
        if r6
          if has_terminal?('within', false, index)
            r7 = instantiate_node(SyntaxNode,input, index...(index + 6))
            @index += 6
          else
            terminal_parse_failure('within')
            r7 = nil
          end
          s0 << r7
          if r7
            r8 = _nt_ws
            s0 << r8
            if r8
              r9 = _nt_range_list
              s0 << r9
            end
          end
        end
      end
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(WithinRelation1)
      r0.extend(WithinRelation2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:within_relation][start_index] = r0

    r0
  end

  module Expr0
    def ws1
      elements[0]
    end

    def ws2
      elements[2]
    end

    def v
      elements[3]
    end
  end

  module Expr1
    def m
      elements[1]
    end
  end

  module Expr2
    def value
      return 'n % ' + m.v.value if !m.empty?
      'n'
    end
  end

  def _nt_expr
    start_index = index
    if node_cache[:expr].has_key?(index)
      cached = node_cache[:expr][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    if has_terminal?('n', false, index)
      r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
      @index += 1
    else
      terminal_parse_failure('n')
      r1 = nil
    end
    s0 << r1
    if r1
      i3, s3 = index, []
      r4 = _nt_ws
      s3 << r4
      if r4
        if has_terminal?('mod', false, index)
          r5 = instantiate_node(SyntaxNode,input, index...(index + 3))
          @index += 3
        else
          terminal_parse_failure('mod')
          r5 = nil
        end
        s3 << r5
        if r5
          r6 = _nt_ws
          s3 << r6
          if r6
            r7 = _nt_number
            s3 << r7
          end
        end
      end
      if s3.last
        r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
        r3.extend(Expr0)
      else
        @index = i3
        r3 = nil
      end
      if r3
        r2 = r3
      else
        r2 = instantiate_node(SyntaxNode,input, index...index)
      end
      s0 << r2
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(Expr1)
      r0.extend(Expr2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:expr][start_index] = r0

    r0
  end

  module RangeList0
    def r
      elements[3]
    end
  end

  module RangeList1
    def h
      elements[0]
    end

    def t
      elements[1]
    end
  end

  module RangeList2
    def value
      b = t.elements.map{|x| x.r.value}.flatten(1)
      [h.value, *b]
    end
  end

  def _nt_range_list
    start_index = index
    if node_cache[:range_list].has_key?(index)
      cached = node_cache[:range_list][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    i1 = index
    r2 = _nt_range
    if r2
      r1 = r2
    else
      r3 = _nt_number
      if r3
        r1 = r3
      else
        @index = i1
        r1 = nil
      end
    end
    s0 << r1
    if r1
      s4, i4 = [], index
      loop do
        i5, s5 = index, []
        r7 = _nt_ws
        if r7
          r6 = r7
        else
          r6 = instantiate_node(SyntaxNode,input, index...index)
        end
        s5 << r6
        if r6
          if has_terminal?(',', false, index)
            r8 = instantiate_node(SyntaxNode,input, index...(index + 1))
            @index += 1
          else
            terminal_parse_failure(',')
            r8 = nil
          end
          s5 << r8
          if r8
            r10 = _nt_ws
            if r10
              r9 = r10
            else
              r9 = instantiate_node(SyntaxNode,input, index...index)
            end
            s5 << r9
            if r9
              r11 = _nt_range_list
              s5 << r11
            end
          end
        end
        if s5.last
          r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
          r5.extend(RangeList0)
        else
          @index = i5
          r5 = nil
        end
        if r5
          s4 << r5
        else
          break
        end
      end
      r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
      s0 << r4
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(RangeList1)
      r0.extend(RangeList2)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:range_list][start_index] = r0

    r0
  end

  module Number0
    def value
      text_value
    end
  end

  def _nt_number
    start_index = index
    if node_cache[:number].has_key?(index)
      cached = node_cache[:number][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    s0, i0 = [], index
    loop do
      if has_terminal?('\G[0-9]', true, index)
        r1 = true
        @index += 1
      else
        r1 = nil
      end
      if r1
        s0 << r1
      else
        break
      end
    end
    if s0.empty?
      @index = i0
      r0 = nil
    else
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(Number0)
    end

    node_cache[:number][start_index] = r0

    r0
  end

  module Range0
    def a
      elements[0]
    end

    def b
      elements[2]
    end
  end

  module Range1
    def value
      return [a.value, b.value]
    end
  end

  def _nt_range
    start_index = index
    if node_cache[:range].has_key?(index)
      cached = node_cache[:range][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    i0, s0 = index, []
    r1 = _nt_number
    s0 << r1
    if r1
      if has_terminal?('..', false, index)
        r2 = instantiate_node(SyntaxNode,input, index...(index + 2))
        @index += 2
      else
        terminal_parse_failure('..')
        r2 = nil
      end
      s0 << r2
      if r2
        r3 = _nt_number
        s0 << r3
      end
    end
    if s0.last
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(Range0)
      r0.extend(Range1)
    else
      @index = i0
      r0 = nil
    end

    node_cache[:range][start_index] = r0

    r0
  end

  module Ws0
    def value
      ''
    end
  end

  def _nt_ws
    start_index = index
    if node_cache[:ws].has_key?(index)
      cached = node_cache[:ws][index]
      if cached
        cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
        @index = cached.interval.end
      end
      return cached
    end

    s0, i0 = [], index
    loop do
      if has_terminal?('\G[\\s]', true, index)
        r1 = true
        @index += 1
      else
        r1 = nil
      end
      if r1
        s0 << r1
      else
        break
      end
    end
    if s0.empty?
      @index = i0
      r0 = nil
    else
      r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
      r0.extend(Ws0)
    end

    node_cache[:ws][start_index] = r0

    r0
  end

end

class PluralRulesParser < Treetop::Runtime::CompiledParser
  include PluralRules
end


