module Rasti

module DB
  module NQL
    grammar Syntax

      rule sentence
        space* proposition:proposition space* <Nodes::Sentence>
      end

      rule proposition
        disjunction /
        conjunction /
        statement
      end

      rule disjunction
        left:(conjunction / statement) space* '|' space* right:proposition <Nodes::Disjunction>
      end

      rule conjunction
        left:statement space* '&' space* right:(conjunction / statement) <Nodes::Conjunction>
      end

      rule statement
        parenthesis_sentence /
        comparison
      end

      rule parenthesis_sentence
        '(' sentence ')' <Nodes::ParenthesisSentence>
      end

      rule comparison
        comparison_not_include           /
        comparison_include               /
        comparison_like                  /
        comparison_greater_than_or_equal /
        comparison_less_than_or_equal    /
        comparison_greater_than          /
        comparison_less_than             /
        comparison_not_equal             /
        comparison_equal
      end

      rule attribute
        _tables:(table:attribute_name '.')* _column:attribute_name <Nodes::Attribute>
      end

      rule comparison_include
        attribute:attribute space* comparator:':' space* argument:argument <Nodes::Comparisons::Include>
      end

      rule comparison_not_include
        attribute:attribute space* comparator:'!:' space* argument:argument <Nodes::Comparisons::NotInclude>
      end

      rule comparison_like
        attribute:attribute space* comparator:'~' space* argument:argument <Nodes::Comparisons::Like>
      end

      rule comparison_greater_than
        attribute:attribute space* comparator:'>' space* argument:argument <Nodes::Comparisons::GreaterThan>
      end

      rule comparison_greater_than_or_equal
        attribute:attribute space* comparator:'>=' space* argument:argument <Nodes::Comparisons::GreaterThanOrEqual>
      end

      rule comparison_less_than
        attribute:attribute space* comparator:'<' space* argument:argument <Nodes::Comparisons::LessThan>
      end

      rule comparison_less_than_or_equal
        attribute:attribute space* comparator:'<=' space* argument:argument <Nodes::Comparisons::LessThanOrEqual>
      end

      rule comparison_not_equal
        attribute:attribute space* comparator:'!=' space* argument:argument <Nodes::Comparisons::NotEqual>
      end

      rule comparison_equal
        attribute:attribute space* comparator:'=' space* argument:argument <Nodes::Comparisons::Equal>
      end

      rule argument
        array /
        basic
      end

      rule basic
        boolean        /
        time           /
        float          /
        integer        /
        literal_string /
        string
      end

      rule array
        open:'[' space* contents:(array_content / basic) space* close:']' <Nodes::Constants::Array>
      end

      rule array_content
        left:basic space* ',' space* right:(array_content / basic) <Nodes::ArrayContent>
      end

      rule space
        [\s\t\n]
      end

      rule attribute_name
        [a-z_]+
      end

      rule time
        date:(value:date 'T')? hour:(digit digit) ':' minutes:(digit digit) seconds:(':' value:(digit digit))? timezone:(value:timezone)? <Nodes::Constants::Time>
      end

      rule date
        year:(digit digit digit digit) '-' month:(digit digit) '-' day:(digit digit)
      end

      rule timezone
        sign:sign hour:(digit digit) ':' minutes:(digit digit)
      end

      rule sign
        '+' / 
        '-'
      end

      rule literal_string
        '"' string:any_character+ '"' <Nodes::Constants::LiteralString>
      end

      rule string
        valid_character+ <Nodes::Constants::String>
      end

      rule any_character
        valid_character /
        reserved_character
      end

      rule valid_character 
        [0-9a-zA-ZÁÀÄÂÃÅĀĂǍáàäâãåāăǎÉÈËÊĒĔĖĚéèëêēĕėěÍÌÏÎĨĬǏíìïîĩĭǐÓÒÖÔÕŌŎŐǑóòöôõōŏőǒÚÙÜÛŨŪŬŮŰǓúùüûũūŭůűǔÑñçÇ%@#+\--Z\\^_'?!$*/\s]
      end

      rule boolean
        true /
        false
      end

      rule true
        'true' <Nodes::Constants::True>
      end

      rule false
        'false' <Nodes::Constants::False>
      end

      rule float
        digit+ '.' digit+ <Nodes::Constants::Float>
      end

      rule integer
        digit+ <Nodes::Constants::Integer>
      end

      rule digit
        [0-9]
      end

      rule reserved_character
        [&|.():!=<>~,\]\[]
      end

    end
  end
end

end