packages feed

qudb-0.0.0: Database/QUDB/Parser.y

{
module Database.QUDB.Parser (parse) where
import Database.QUDB.Scanner
import qualified Database.QUDB.EntityTypes as T
import qualified Database.QUDB.Query as Q
}

%name parseTokens
%tokentype { Token }
%error { parseError }

%token
      str    { Str $$ }
      int    { Int $$ }
      symb   { Symb $$ }
      '*'    { Asterisk }
      '('    { LParen }
      ')'    { RParen }
      ','    { Comma }
      select { Select }
      insert { Insert }
      delete { Delete }
      update { Update }
      from   { From }
      into   { Into }
      values { Values }
      table  { Table }
      create { Create }
      drop   { Drop }
      where  { Where }
      set    { Set }
      and    { And }
      or     { Or }
      asc    { Asc }
      desc   { Desc }
      limit  { Limit }
      '='    { Equals }
      '>'    { Greater }
      '<'    { Lesser }
      ';'    { Semicolon }
      orderBy { OrderBy }
%%

Query : QueryWithoutSemicolon ';' { $1 }

QueryWithoutSemicolon : SelectQuery { $1 }
                      | InsertQuery { $1 }
                      | DeleteQuery { $1 }
                      | UpdateQuery { $1 }
                      | CreateTableQuery { $1 }
                      | DropTableQuery { $1 }

SelectQuery : select '*' from Table Clauses     { Q.SelectAll $4 : $5 }
            | select Columns from Table Clauses { Q.Select $4 $2 : $5 }

InsertQuery: insert into Table values '(' Values ')' { [Q.Insert $3 $6] }

DeleteQuery : delete from Table OptWhereClause { Q.Delete $3 : $4 }

UpdateQuery : update Table set UpdatedValues OptWhereClause { Q.Update $2 $4 : $5 }

CreateTableQuery : create table Table '(' ColumnsDefs ')' { [Q.CreateTable $3 $5] }

DropTableQuery : drop table Table { [Q.DropTable $3] }

Values : Value OtherValues { $1 : $2 }

OtherValues : ',' Value OtherValues { $2 : $3 }
            | {- empty -} { [] }

Value : str { T.StringValue $1 }
      | int { T.IntValue $1 }

UpdatedValues : UpdatedValue OptUpdatedValues { $1 : $2 }

UpdatedValue : ColumnName '=' Value { ($1, $3) }

OptUpdatedValues : ',' UpdatedValue OptUpdatedValues { $2 : $3 }
                 | {- empty -}                       { [] }

Table : symb { $1 }

Columns : ColumnName OtherColumnNames { $1 : $2 }

OtherColumnNames: ',' ColumnName OtherColumnNames { $2 : $3 }
                | {- empty -} { [] }

ColumnName : symb { $1 }

ColumnsDefs : ColumnDef OtherColumnsDefs { $1 : $2 }

OtherColumnsDefs : ',' ColumnDef OtherColumnsDefs { $2 : $3 }
                 | {- empty -} { [] }

ColumnDef : symb symb { case $2 of
                          "int"     -> ($1, T.Int)
                          "string"  -> ($1, T.String)
                          otherwise -> error $ "No such type: " ++ $2 }

Clauses : Clause Clauses { $1 : $2 }
        | {- empty -}    { [] }

Clause : WhereClause { $1 }
       | OrderByClause { $1 }
       | LimitClause { $1 }

OrderByClause : orderBy OrderSpecs { Q.OrderBy $2 }

OrderSpecs : OrderSpec OptOrderSpecs { $1 : $2 }

OptOrderSpecs : ',' OrderSpec OptOrderSpecs { $2 : $3 }
              | {- empty -}                 { [] }

OrderSpec : ColumnName asc   { ($1, Q.Ascending) }
          | ColumnName desc  { ($1, Q.Descending) }
          | ColumnName       { ($1, Q.Ascending) }

OptWhereClause : WhereClause { [$1] }
               | {- empty -} { [] }

LimitClause : limit int { Q.Limit $2 }

WhereClause : where Predicates { Q.Where $2 }

Predicates : Predicate and PredicateConj { Q.AndConditions ($1:$3) }
           | Predicate or  PredicateDisj { Q.OrConditions ($1:$3) }
           | Predicate { $1 }

PredicateConj : Predicate and PredicateConj { $1 : $3 }
              | Predicate { [$1] }

PredicateDisj : Predicate or  PredicateDisj { $1 : $3 }
              | Predicate { [$1] }

Predicate : ColumnName '=' Value { Q.Condition $1 (== $3) }
          | ColumnName '<' Value { Q.Condition $1 (< $3) }
          | ColumnName '>' Value { Q.Condition $1 (> $3) }

{
parseError :: [Token] -> a
parseError (t:_) = error ("Parse error at " ++ show t)

parse = parseTokens . scan
}