#
############################################################################
# File : grammar.pl #
# Author : Supun Ruwanpura #
# Date : 19-10-2000 #
############################################################################
use strict;
my $grammar = q{
############################################################################
translate : learned | count | sum | average | select | { unknown_msg() }
############################################################################
select : (ask|question) qualifier(?) /(our)?/ table eol
{ Select_T1_F0_C0($item[4]) }
| (ask|question) qualifier(?) field /of/ qualifier(?) table eol check[$item[3],$item[6]]
{ Select_T1_F1_C0($item[3],$item[6]) }
| (ask|question) qualifier(?) /(our)?/ table /'?/ qualifier(?) field eol check[$item[7],$item[4]]
{ Select_T1_F1_C0($item[7],$item[4]) }
| (ask|question) qualifier(?) field /and/ field /of/ qualifier(?) table eol check[$item[3],$item[8]] check[$item[5],$item[8]]
{ Select_T1_F2_C0($item[3],$item[5],$item[8]) }
| (ask|question) qualifier(?) /(our)?/ table /'?/ qualifier(?) field /and/ field eol check[$item[7],$item[4]] check[$item[9],$item[4]]
{ Select_T1_F2_C0($item[7],$item[9],$item[4]) }
| (ask|question) qualifier(?) /(our)?/table ignore_words condition eol
{ Select_T1_F0_C1($item[4], $item[6]) }
| (ask|question) qualifier(?) field /of/ qualifier(?) table ignore_words condition eol check[$item[3],$item[6]]
{ Select_T1_F1_C1($item[3],$item[6],$item[8]) }
| (ask|question) qualifier(?) /(our)?/ table /'?/ qualifier(?) field ignore_words condition eol check[$item[7],$item[4]]
{ Select_T1_F1_C1($item[7],$item[4],$item[9]) }
| (ask|question) qualifier(?) field /and/ field /of/ qualifier(?) table ignore_words condition eol check[$item[3],$item[8]] check[$item[5],$item[8]]
{ Select_T1_F2_C1($item[3],$item[5],$item[8],$item[10]) }
| (ask|question) qualifier(?) /(our)?/ table /'?/ qualifier(?) field /and/ field ignore_words condition eol check[$item[7],$item[4]] check[$item[9],$item[4]]
{ Select_T1_F2_C1($item[7],$item[9],$item[4],$item[11]) }
| (ask|question) qualifier(?) /(our)?/ table /and/ table eol related[$item[4],$item[6]]
{ Select_T2_F0_C0($item[4], $item[6]) }
| (ask|question) ignore_words table ignore_words table ignore_words eol related[$item[3],$item[5]]
{ Select_T2_F0_C0($item[3], $item[5]) }
############################################################################
learned : {}
############################################################################
count : ask_count table /((is|are) there)|((do)? we have)/ eol
{ Count_T1_F0_C0( $item[2] ) }
| ask qualifier(?) table /count/ eol
{ Count_T1_F0_C0( $item[3] ) }
| ask_count table prep /(the)?/ field (prep)(?) value /((is|are) there)|((do )?we have)/ eol
{ Count_T1_F0_C1( $item[2], "WHERE $item[5] = " . format_val($item[7])) }
| ask_count table ignore_words condition ignore_words eol
{ Count_T1_F0_C1( $item[2], $item[4]) }
############################################################################
sum : (ask|whats) qualifier(?) total field ignore_words table ignore_words eol check[$item[4],$item[6]]
{ Sum_T1_F1_C0( $item[4], $item[6] ) }
| (ask|whats) qualifier(?) total field ignore_words table ignore_words condition ignore_words eol check[$item[4],$item[6]]
{ Sum_T1_F1_C1( $item[4], $item[6], $item[8] ) }
############################################################################
average : (ask|whats) qualifier(?) /average/ field ignore_words table ignore_words eol check[$item[4],$item[6]]
{ Average_T1_F1_C0($ item[4], $item[6] ) }
| (ask|whats) qualifier(?) /average/ field ignore_words table ignore_words condition ignore_words eol check[$item[4],$item[6]]
{ Average_T1_F1_C1( $item[4], $item[6], $item[8] ) }
############################################################################
field : FIELDS ### column names ###
table : TABLES ### table names ###
############################################################################
qualifier : /the|every|all( the)?|any|our/
ask : reply to_me
ask_count : ask(?) /how (many|much)/|/what number of|count the number of/
total : /total|sum of( all)( the)/
pre_val : /(by|of|for|to|from|with|is|are)*/
reply : /tell|show|list|display/
value : date|number|word
number : /(\$?)(-?)\d+(\.?)\d*/
word : /\w+|\"[\S\s]*\"/ { qq{ $item[1] } }
to_me : /((to )?(me|us))?/
question : whats|whos
whats : /what's|what're|what (is|are)?/
whos : /who's|who're|who (is|are)|who/
prep : /for|of|with|by/
table_verb : table|field
ignore_words : junk(s?)
junk : ...!table_verb /\S+/
eol : /\s*/ /[.?]?/ /\s*/ /\z/
############################################################################
### date strings ###
date : /today|tomorrow|yesterday/ { parse_date($item[1]) }
| day { parse_date($item[1]) }
| /(last|previous|next) /(date_period) { parse_date($item[1].' '.$item[2]) }
| (date_format)
date_period : /week|month/|month|day|/(financial )?year/
month : long_month|short_month
long_month : /january|february|march|april|may|june|july|august|september|october|november|december/
short_month : /jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/
day : long_day|short_day
long_day : /sunday|monday|tuesday|wednesday|thursday|friday|saturday/
short_day : /sun|mon|tue|wed|thu|fri|sat/
date_format : DD date_sep (MM|month) date_sep (YYYY|YY) { parse_date($item[3].'/'.$item[1].'/'.$item[5]) }
| (MM|month) date_sep DD date_sep (YYYY|YY) { parse_date($item[1].'/'.$item[3].'/'.$item[5]) }
| month DD /,?/(YYYY|YY) { parse_date($item[1].'/'.$item[2].'/'.$item[4]) }
| (YYYY|YY) date_sep (MM|month) date_sep DD { parse_date($item[3].'/'.$item[5].'/'.$item[1]) }
| DD date_sep (MM|month) { parse_date($item[3].'/'.$item[1]) }
| (MM|month) date_sep DD { parse_date($item[1].'/'.$item[3]) }
| month DD { parse_date($item[1].'/'.$item[2]) }
date_sep : /-|\//
DD : /\d{1,2}/ # 31 || $item[1] < 1}>
MM : /\d{1,2}/ # 12 || $item[1] < 1}>
YYYY : /\d{4}/
YY : /\d{2}/
############################################################################
### Conditions ###
condition : greater_than|less_than|between|like|equal
equal : field pre_equal value
{ "WHERE $item[1] = " . format_val($item[3]) }
pre_equal : /by|of|for|to|from|with|is|are|equal( to)/
greater_than: field pre_greater value
{ "WHERE $item[1] > " . format_val($item[3]) }
pre_greater : /(is |are )?/ /more|greater|higher|expensive|taller|bigger/ /than/
less_than : field pre_less value
{ "WHERE $item[1] < " . format_val($item[3]) }
pre_less : /(is |are )?/ /less|lower|cheaper|shorter|smaller/ /than/
between : field pre_between value /and/ value
{ "WHERE $item[1] >= " . format_val($item[3]) . "\n\tAND $item[1] <= " . format_val($item[5]) }
pre_between : /(is |are )?/ /between/
like : field /starts?/ /with/ value
{ $item[4] =~ s/ //g;"WHERE $item[1] LIKE \"$item[4]%\"" }
| field /ends?|ended/ /in/ value
{ $item[4] =~ s/ //g;"WHERE $item[1] LIKE \"%$item[4]\"" }
| field /contains?/ value
{ $item[3] =~ s/ //g; "WHERE $item[1] LIKE \"%$item[3]%\"" }
############################################################################
### check if the given field ($arg[0]) is found in the given table ($arg[1]) ###
check :
### check if there is any relationship between two given tables ($arg[0] and $arg[1] ###
related :
}; ### end of pre-defined grammar ###
do "grammar_func.pl"; ### append various grammar functions to this grammar ###
$grammar; ### return the grammar ###