%{ (* Header: Define the AST type *) open Ast %} %token SELECT ALL DISTINCT FROM WHERE %token LEFT RIGHT FULL INNER OUTER %token CROSS NATURAL UNION JOIN %token GREATER_THAN_OPERATOR LESS_THAN_OPERATOR EQUALS_OPERATOR %token IDENT %token COMMA DOT %token ASTERISK %token AS ON %token OR AND NOT %token EOF %start main %type main %% main: | select_stmt EOF { Query($1) } select_stmt : | SELECT select_list table_expression { Select($2, $3) } | SELECT set_identifier select_list table_expression { Select($3, $4) } set_identifier : | ALL {} | DISTINCT {} select_list : | ASTERISK { [Asterisk] } | select_sublist {$1} select_sublist : | IDENT { [Column($1)] } | select_sublist COMMA IDENT { Column($3)::$1 } table_expression: | from_clause { $1 } | from_clause where_clause { $1 } from_clause : | FROM table_reference_list { $2 } table_reference_list : | table_reference { [$1] } | table_reference_list COMMA table_reference { $3::$1 } table_reference : | table_primary_or_joined_table { $1 } (* | table_primary_or_joined_table sample_clause { $1 } *) table_primary_or_joined_table: | table_primary { $1 } | joined_table { $1 } table_primary : | table_or_query_name { $1 } table_or_query_name: | table_name { $1 } joined_table : | cross_join { $1 } | qualified_join { $1 } | natural_join { $1 } | union_join { $1 } cross_join: | table_reference CROSS JOIN table_primary { Join($1, Cross, $4, None) } qualified_join: | table_reference JOIN table_reference join_specification { Join($1, Left, $3, $4) } | table_reference join_type JOIN table_reference join_specification { Join($1, $2, $4, $5) } join_specification: | join_condition { $1 } join_condition: | ON search_condition { Some($2) } natural_join: | table_reference NATURAL JOIN table_primary { Join($1, Natural, $4, None) } | table_reference NATURAL join_type JOIN table_primary { Join($1, Natural, $5, None) } union_join: | table_reference UNION JOIN table_primary { Join($1, Union, $4, None) } table_name : | IDENT { Table($1) } join_type: | INNER { Inner } | outer_join_type { $1 } | outer_join_type OUTER { $1 } outer_join_type: | LEFT { Left } | RIGHT { Right } | FULL { Full } where_clause : | WHERE search_condition { } search_condition: (*| IDENT EQUALS_OPERATOR IDENT {}*) | boolean_value_expression { $1 } boolean_value_expression: | boolean_term { $1 } | boolean_value_expression OR boolean_term { Or($1, $3) } boolean_term: | boolean_factor { $1 } | boolean_term AND boolean_factor { And($1, $3) } boolean_factor: | boolean_test { $1 } | NOT boolean_test { Not($2) } boolean_test: | boolean_primary { $1 } boolean_primary : | predicate { $1 } (*| boolean_predicand {}*) predicate : | comparison_predicate { $1 } comparison_predicate : | row_value_predicand comparison_predicate_part2 { Condition($1, $2) } comparison_predicate_part2: | comp_op row_value_predicand { Comparison($1, $2) } comp_op : | EQUALS_OPERATOR { Equals } | not_equals_operator { NotEquals } | LESS_THAN_OPERATOR { LessThan } | GREATER_THAN_OPERATOR { GreaterThan } | less_than_or_equals_operator { LessEquals } | greater_than_or_equals_operator { GreaterEquals } not_equals_operator : | LESS_THAN_OPERATOR GREATER_THAN_OPERATOR {} less_than_or_equals_operator: | LESS_THAN_OPERATOR EQUALS_OPERATOR {} greater_than_or_equals_operator: | GREATER_THAN_OPERATOR EQUALS_OPERATOR {} row_value_predicand: | row_value_special_case { $1 } row_value_special_case : | nonparenthesized_value_expression_primary { $1 } nonparenthesized_value_expression_primary: | column_reference { $1 } column_reference: | basic_identifier_chain { $1 } basic_identifier_chain: | identifier_chain { $1 } identifier_chain: | IDENT { $1 } (*| identifier_chain DOT IDENT {}*) boolean_predicand: | nonparenthesized_value_expression_primary {}