DaveVoorhis / Rel

Rel is a desktop database management system that implements Date & Darwen's "Tutorial D" database language.
https://reldb.org
Apache License 2.0
100 stars 8 forks source link

Grammar railroad diagram #9

Closed mingodad closed 1 year ago

mingodad commented 1 year ago

After massaging a bit the grammar shown here https://reldb.org/TutorialD.html (basically removing <> and replacing : by ::= we can have an EBNF grammar accepted by https://www.bottlecaps.de/rr/ui to produce a navigable railroad diagram (https://en.wikipedia.org/wiki/Syntax_diagram).

Copy and paste the EBNF shown bellow at https://www.bottlecaps.de/rr/ui on the tab Edit Grammar then switch/click to the tab View Diagram.

evaluate    ::= ( compound_statement_body ";" )? expression ( EOT | EOF )
statement_list  ::= ( statement )*
code    ::= statement_list ( EOT | EOF )
statement   ::= statement_body ";"
op_before_returns   ::= OPERATOR identifier "(" ( identifier type_ref ( "," identifier type_ref )* )? ")"
op_after_returns    ::= op_updates op_synonym op_version ";" op_body END ( OPERATOR )?
|   identifier FOREIGN ( TEXT )* ENDFOREIGN ( OPERATOR )?
getoperatorreturntype   ::= op_before_returns op_returns op_after_returns
getheading  ::= heading
getsignature    ::= op_signature op_returns
statement_body  ::= assignment
|   loop
|   op_def
|   type_def
|   drop
|   alter
|   var_def
|   db_constraint_def
|   relation_array_load
|   begin_transaction
|   compound_statement_body
|   commit
|   rollback
|   call
|   return_statement
|   case_statement
|   if_statement
|   leave
|   write
|   writeln
|   output
|   announce
|   execute
|   set
|   backup
/* Rel extension - non-TTM */
backup  ::= BACKUP
/* Rel extension - non-TTM */
write   ::= WRITE expression
/* Rel extension - non-TTM */
writeln ::= WRITELN ( expression )?
/* Rel extension - non-TTM */
output  ::= OUTPUT expression
/* Rel extension - non-TTM */
announce    ::= ANNOUNCE string_literal
/* Rel extension - non-TTM */
execute ::= EXECUTE expression
/* Rel extension - non-TTM */
set ::= SET identifier identifier
compound_statement_body ::= BEGIN ";" statement_list END
op_def  ::= OPERATOR identifier "(" parameter_def_commalist ")" op_returns ( rel_op_def | external_op_def )
lambda  ::= OPERATOR lambda_definition END ( OPERATOR )?
|   LAMBDA lambda_definition LAMBDAEND
lambda_definition   ::= "(" parameter_def_commalist ")" RETURNS type_ref ";" op_body
external_op_def ::= identifier FOREIGN ( TEXT )* ENDFOREIGN ( OPERATOR )?
rel_op_def  ::= op_updates op_synonym op_version ";" op_body END ( OPERATOR )?
/* Note: op_returns() and op_updates()
should be mutually exclusive. */
op_returns  ::= ( RETURNS type_ref )?
op_updates  ::= ( UPDATES "{" ( ALL BUT parameter_name_commalist )? "}" )?
op_synonym  ::= ( synonym_def )?
op_version  ::= ( VERSION identifier )?
op_body ::= statement_list
return_statement    ::= RETURN ( expression )?
/* Not explicitly defined in TTM3 */
parameter_def_commalist ::= ( parameter_def ( "," parameter_def )* )?
parameter_def   ::= identifier type_ref
/* Not explicitly defined in TTM3 */
parameter_name_commalist    ::= ( identifier ( "," identifier )* )?
synonym_def ::= SYNONYMS "{" user_op_name_commalist "}"
/* Not explicitly defined in TTM3 */
user_op_name_commalist  ::= identifier ( "," identifier )*
/* Inclusion of type_ref_commalist() in
OPERATOR DROP is not per TTM3,
but necessary to 
disambiguate operators. */
drop    ::= DROP ( OPERATOR op_signature | VAR identifier | CONSTRAINT identifier | TYPE identifier )
op_signature    ::= identifier "(" type_ref_commalist ")"
alter   ::= ALTER alter_var
alter_var   ::= VAR identifier alter_var_action_optional ( var_keydeflist )?
alter_var_action_optional   ::= ( alter_var_action )*
alter_var_action    ::= RENAME identifier TO identifier
|   TYPE_OF identifier TO type_ref
|   INSERT attribute_spec
|   DROP identifier
op_type ::= OPERATOR "(" type_ref_commalist ")" ( RETURNS type_ref )?
type_ref_commalist  ::= ( type_ref ( "," type_ref )* )?
/* Was user_scalar_type_def */
type_def    ::= TYPE identifier type_def_kind
type_def_kind   ::= type_def_external
|   type_def_internal
type_def_external   ::= identifier FOREIGN ( TEXT )* ENDFOREIGN ( TYPE )?
/* User-defined (internal) types start here */
type_def_internal   ::= type_def_internal_ordinal type_def_internal_union type_def_internal_is_or_possrep
type_def_internal_is_or_possrep ::= is_def
|   possrep_def_list
type_def_internal_ordinal   ::= ( type_def_internal_opt_ordinal )?
type_def_internal_opt_ordinal   ::= ( ORDINAL | ORDERED )
type_def_internal_union ::= ( type_def_internal_opt_union )?
type_def_internal_opt_union ::= UNION
is_def  ::= IS "{" ( single_inheritance_is_def | multiple_inheritance_is_def ) "}"
single_inheritance_is_def   ::= identifier possrep_or_specialization_details
possrep_or_specialization_details   ::= specialisation_constraint_def ( derived_possrep_def_list )?
|   possrep_def_list
multiple_inheritance_is_def ::= scalar_type_name_commalist derived_possrep_def_list
/* Not explicitly defined in TTM3 */
scalar_type_name_commalist  ::= scalar_type_name ( "," scalar_type_name )*
scalar_type_name    ::= identifier
/* Not explicitly defined in TTM3 */
possrep_def_list    ::= ( possrep_def )* possrep_opt_initialiser
/* Not defined in TTM3.  For explicitly setting
values of components not in the current possrep.  
Only required by types with multiple possreps.
Takes the place of "highly protected
operators not part of D". (pg 382, etc.) */
possrep_opt_initialiser ::= ( INIT possrep_initialiser_assignments ( possrep_initialiser_assignments )* )?
/* Not defined in TTM3, as per above.
Identifier should be existing POSSREP name. */
possrep_initialiser_assignments ::= identifier "(" assignment ")"
possrep_def ::= POSSREP possrep_def_identifier ( "{" | "(" ) possrep_component_def_commalist possrep_opt_constraint_def ( "}" | ")" )
possrep_def_identifier  ::= ( identifier )?
possrep_opt_constraint_def  ::= ( constraint_def )?
/* Not explicitly defined in TTM3 */
possrep_component_def_commalist ::= ( possrep_component_def ( "," possrep_component_def )* )?
possrep_component_def   ::= identifier type_ref
/* Expression must be boolean */
constraint_def  ::= CONSTRAINT expression
/* Expression must be boolean */
specialisation_constraint_def   ::= CONSTRAINT expression
/* Not explicitly defined in TTM3 */
derived_possrep_def_list    ::= derived_possrep_def ( derived_possrep_def )*
derived_possrep_def ::= POSSREP derived_possrep_def_opt_identifier ( "(" | "{" ) derived_possrep_component_def_commalist ( "}" | ")" )
derived_possrep_def_opt_identifier  ::= ( identifier )?
/* Not explicitly defined in TTM3 */
derived_possrep_component_def_commalist ::= derived_possrep_component_def ( "," derived_possrep_component_def )*
derived_possrep_component_def   ::= identifier "=" identifier "(" identifier ")"
/* End user-defined types (internal) */

/* Includes scalar_var_def,
relation_var_def,
tuple_var_def */
var_def ::= VAR identifier ( var_scalar_or_tuple | var_relvar )
var_relvar  ::= ( REAL | BASE ) var_type_or_init_value var_keydeflist
|   PRIVATE var_type_or_init_value var_keydeflist
|   PUBLIC type_ref var_keydeflist
|   VIRTUAL expression var_keydeflistoptional
|   var_relvar_external
var_relvar_external ::= EXTERNAL identifier string_literal ( identifier )?
var_keydeflist  ::= var_keydef ( var_keydef )*
var_keydeflistoptional  ::= ( var_keydef )*
var_keydef  ::= KEY "{" attribute_name_list "}"
var_scalar_or_tuple ::= var_type_or_init_value
var_type_or_init_value  ::= var_type_and_optional_init
|   var_init
var_type_and_optional_init  ::= type_ref ( INIT "(" expression ")" )?
var_init    ::= INIT "(" expression ")"
db_constraint_def   ::= CONSTRAINT identifier expression
/* type -- scalar_type, tuple_type, relation_type */
type_ref    ::= identifier
|   type_same_type_as
|   tuple_type
|   relation_type
|   op_type
|   type_array
type_array  ::= ARRAY type_ref
type_same_type_as   ::= SAME_TYPE_AS "(" expression ")"
tuple_type  ::= TUPLE heading_type
relation_type   ::= RELATION heading_type
heading_type    ::= heading
|   same_heading_as
same_heading_as ::= SAME_HEADING_AS "(" expression ")"
relation_array_load ::= LOAD identifier FROM expression
begin_transaction   ::= BEGIN TRANSACTION
commit  ::= COMMIT
rollback    ::= ROLLBACK
case_statement  ::= CASE ";" when_def_list case_else END ( CASE )?
when_def_list   ::= when_def ( when_def )*
when_def    ::= WHEN expression THEN statement_list
case_else   ::= ( ELSE statement_list )?
/* Note that THEN and ELSE are not
followed by semicolons, but maybe should be? */
if_statement    ::= IF expression THEN statement_list if_statement_else END ( IF )?
if_statement_else   ::= ( ELSE statement_list )?
loop    ::= ( identifier ":" )? ( do_statement | while_statement | for_statement )
do_statement    ::= DO identifier ":=" expression TO expression ";" statement_list END ( DO )?
while_statement ::= WHILE expression ";" statement_list END ( WHILE )?
for_statement   ::= FOR expression ";" statement_list END ( FOR )?
leave   ::= LEAVE identifier
call    ::= CALL identifier "(" arglist ")"
assignment  ::= assign ( "," assign )*
assign  ::= identifier ":=" expression
|   INSERT identifier expression
|   D_INSERT identifier expression
|   DELETE identifier delete_parameter
|   I_DELETE identifier expression
|   UPDATE identifier update_where ":" update_assignment
delete_parameter    ::= ( ( WHERE )? expression )?
update_where    ::= ( WHERE expression )?
update_assignment   ::= "{" ( assignment )? "}"
/* Expressions */
expression  ::= ( attribute_from | basic_expression | tuple_from | with | tclose )
attribute_from  ::= identifier FROM expression
tuple_from  ::= TUPLE FROM expression
with    ::= WITH "(" name_intro_commalist ")" ":" expression
name_intro_commalist    ::= name_intro ( "," name_intro )*
name_intro  ::= identifier ":=" expression
tclose  ::= TCLOSE expression
basic_expression    ::= order_expression ( "[" expression "]" | "(" arglist ")" )?
order_expression    ::= where_expression ( ( ORDER "(" order_item_commalist ")" | UNORDER "(" ")" ) )?
where_expression    ::= equiv_expression ( WHERE equiv_expression )?
equiv_expression    ::= or_expression ( EQUIV or_expression )*
or_expression   ::= xor_expression ( OR xor_expression )*
xor_expression  ::= and_expression ( XOR and_expression )*
and_expression  ::= compare_expression ( AND compare_expression )*
compare_expression  ::= rel_op ( EQ rel_op | ( NEQ_A | NEQ_U ) rel_op | ( GTE_A | GTE_U ) rel_op | ( LTE_A | LTE_U ) rel_op | GT rel_op | LT rel_op | SUBSET rel_op | SUBSET_OR_EQUAL rel_op | SUPERSET rel_op | SUPERSET_OR_EQUAL rel_op | ( IN | ELEMENT_U ) rel_op )?
/* Parentheses around  WRAP, UNWRAP, GROUP, UNGROUP removed as of 1.0.11
   Infix EXTEND added as of 1.0.20.  Not per Tutorial D spec.
   Infix SUMMARIZE added as of 1.0.20.  Not per Tutorial D spec.
   rel_monadic() and rel_dyadic() combined and changed to rel_op() to
   give monadic and dyadic ops equal precedence.
*/
rel_op  ::= rel_project ( RENAME "{" renaming_commalist "}" | EXTEND ( ":" )? "{" extend_add_commalist "}" | RANK ( BY )? "(" order_item_commalist AS identifier ")" | SUMMARIZE per_or_by ( ":" )? "{" summarize_add_commalist "}" | UPDATE ( ":" )? update_assignment | WRAP wrapping | UNWRAP identifier | GROUP grouping | UNGROUP identifier | DIVIDEBY expression PER "(" expression divide_per_optional ")" | UNION rel_project | XUNION rel_project | D_UNION rel_project | INTERSECT rel_project | MINUS rel_project | I_MINUS rel_project | JOIN rel_project | LEFT JOIN rel_project | RIGHT JOIN rel_project | FULL JOIN rel_project | TIMES rel_project | COMPOSE rel_project | ( SEMIJOIN | MATCHING ) rel_project | ( SEMIMINUS | NOT MATCHING ) rel_project )*
/* Not explicitly defined in TTM3 */
order_item_commalist    ::= ( order_item ( "," order_item )* )?
order_item  ::= ASC identifier
|   DESC identifier
divide_per_optional ::= ( "," expression )?
grouping    ::= "{" attribute_name_list "}" AS identifier
wrapping    ::= "{" attribute_name_list "}" AS identifier
renaming_commalist  ::= ( renaming ( "," renaming )* )?
renaming    ::= renaming_simple
|   renaming_prefix
|   renaming_suffix
renaming_simple ::= identifier AS identifier
renaming_prefix ::= PREFIX string_literal AS string_literal
renaming_suffix ::= SUFFIX string_literal AS string_literal
attribute_name_list ::= optional_all_but attribute_name_commalist
optional_all_but    ::= ( ALL BUT )?
attribute_name_commalist    ::= attribute_name_commalist_attributes_of
|   attribute_name_commalist_list
attribute_name_commalist_attributes_of  ::= ATTRIBUTES_OF "(" expression ")"
attribute_name_commalist_list   ::= ( identifier ( "," identifier )* )?
rel_project ::= add_expression ( "{" attribute_name_list "}" )?
add_expression  ::= mul_expression ( PLUS mul_expression | SUBT mul_expression | BARBAR mul_expression )*
mul_expression  ::= unary_expression ( ( STAR | MULT_U ) unary_expression | ( DIVD_A | DIVD_U ) unary_expression | MODL unary_expression )*
unary_expression    ::= NOT unary_expression
|   PLUS unary_expression
|   SUBT unary_expression
|   primary_expression
primary_expression  ::= literal
|   aggregate_operator
|   exactly
|   nadic_or
|   nadic_equiv
|   nadic_xor
|   nadic_and
|   nadic_union
|   nadic_xunion
|   nadic_disjoint_union
|   nadic_intersect
|   nadic_join
|   nadic_times
|   nadic_compose
|   nadic_count
|   nadic_sum
|   nadic_avg
|   nadic_max
|   nadic_min
|   extend
|   rank
|   summarize
|   substitute
|   case_expression
|   if_expression
|   search
|   type_of
|   image_in
|   fn_invoke
|   dereference
|   "(" expression ")"
search  ::= SEARCH "(" expression "," expression ")"
type_of ::= TYPE_OF "(" expression ")"
image_in    ::= ( BANGBANG_A | BANGBANG_U ) ( image_in_bracketed | image_in_identifier )
|   IMAGE_IN image_in_bracketed
image_in_bracketed  ::= "(" expression ( "," expression )? ")"
image_in_identifier ::= identifier
case_expression ::= CASE when_def_list_expr ELSE expression END ( CASE )?
when_def_list_expr  ::= when_def_expr ( when_def_expr )*
when_def_expr   ::= WHEN expression THEN expression
if_expression   ::= IF expression THEN expression ELSE expression END ( IF )?
/* Update expression, *not* assignment.
Contents of expression() does not change! */
substitute  ::= UPDATE expression ":" update_assignment
nadic_optional_heading  ::= heading "{" heading_exp_commalist "}"
|   "{" heading_exp_commalist "}"
nadic_union ::= UNION nadic_optional_heading
nadic_xunion    ::= XUNION nadic_optional_heading
nadic_disjoint_union    ::= D_UNION nadic_optional_heading
nadic_intersect ::= INTERSECT nadic_optional_heading
nadic_join  ::= JOIN "{" heading_exp_commalist "}"
nadic_times ::= TIMES "{" heading_exp_commalist "}"
nadic_compose   ::= COMPOSE "{" heading_exp_commalist "}"
nadic_or    ::= OR "{" bool_exp_commalist "}"
nadic_equiv ::= EQUIV "{" bool_exp_commalist "}"
nadic_xor   ::= XOR "{" bool_exp_commalist "}"
nadic_and   ::= AND "{" bool_exp_commalist "}"
nadic_count ::= COUNT "{" exp_commalist "}"
nadic_sum   ::= SUM "{" exp_commalist "}"
nadic_avg   ::= AVG "{" exp_commalist "}"
nadic_max   ::= MAX "{" exp_commalist "}"
nadic_min   ::= MIN "{" exp_commalist "}"
exactly ::= EXACTLY "(" expression ( "," expression ( "," expression )* )? ")"
exp_commalist   ::= ( expression ( "," expression )* )?
bool_exp_commalist  ::= ( expression ( "," expression )* )?
heading_exp_commalist   ::= ( expression ( "," expression )* )?
extend  ::= EXTEND expression ":" "{" extend_add_commalist "}"
rank    ::= RANK expression BY "(" order_item_commalist AS identifier ")"
extend_add_commalist    ::= ( extend_add ( "," extend_add )* )?
extend_add  ::= identifier ":=" expression
summarize   ::= SUMMARIZE expression per_or_by ":" "{" summarize_add_commalist "}"
per_or_by   ::= ( PER "(" expression ")" | BY "{" attribute_name_list "}" )?
summarize_add_commalist ::= summarize_add ( "," summarize_add )*
summarize_add   ::= identifier ":=" summary
summary ::= COUNT "(" ")"
|   COUNTD "(" expression ")"
|   SUM "(" expression ")"
|   SUMD "(" expression ")"
|   AVG "(" expression ")"
|   AVGD "(" expression ")"
|   MAX "(" expression ")"
|   MIN "(" expression ")"
|   AND "(" expression ")"
|   OR "(" expression ")"
|   EQUIV "(" expression ")"
|   XOR "(" expression ")"
|   EXACTLY "(" expression "," expression ")"
|   EXACTLYD "(" expression "," expression ")"
|   UNION "(" expression ")"
|   XUNION "(" expression ")"
|   D_UNION "(" expression ")"
|   INTERSECT "(" expression ")"
|   summarize_aggregate
|   summarize_aggregated
|   summarize_userdefined
/* Rel extension. */
summarize_aggregate ::= AGGREGATE "(" expression ( "," expression )? ")" ";" op_body END ( AGGREGATE )?
/* Rel extension. */
summarize_aggregated    ::= AGGREGATED "(" expression ( "," expression )? ")" ";" op_body END ( AGGREGATED )?
/* Rel extension. */
summarize_userdefined   ::= identifier "(" SummarizeItemDistinct expression ( "," expression )? ")"
/* Rel extension. */
SummarizeItemDistinct   ::= ( SummarizeItemDistinctTrue )?
/* Rel extension. */
SummarizeItemDistinctTrue   ::= DISTINCT
fn_invoke   ::= identifier "(" arglist ")"
arglist ::= ( expression ( "," expression )* )?
aggregate_operator  ::= COUNT "(" expression ")"
|   SUM "(" expression "," expression ")"
|   AVG "(" expression "," expression ")"
|   MAX "(" expression "," expression ")"
|   MIN "(" expression "," expression ")"
|   AND "(" expression "," expression ")"
|   OR "(" expression "," expression ")"
|   EQUIV "(" expression "," expression ")"
|   XOR "(" expression "," expression ")"
|   UNION "(" expression "," expression ")"
|   XUNION "(" expression "," expression ")"
|   D_UNION "(" expression "," expression ")"
|   INTERSECT "(" expression "," expression ")"
|   agg_aggregate
agg_aggregate   ::= AGGREGATE ( agg_aggregate_inline | agg_aggregate_userdefined )
/* Rel extension. */
agg_aggregate_inline    ::= "(" expression "," expression ( "," expression )? ")" ";" op_body END ( AGGREGATE )?
/* Rel extension. */
agg_aggregate_userdefined   ::= identifier "(" expression "," expression ( "," expression )? ")"
literal ::= lambda
|   tuple
|   relation
|   integer
|   character
|   rational
|   bool
tuple   ::= TUPLE "{" ( tuple_component_wildcard | ( tuple_component_commalist )? ) "}"
tuple_component_wildcard    ::= STAR
tuple_component_commalist   ::= tuple_component ( "," tuple_component )*
tuple_component ::= identifier expression
relation    ::= RELATION relation_heading "{" tuple_exp_commalist "}"
|   TABLE_DUM
|   TABLE_DEE
relation_heading    ::= ( heading_type )?
heading ::= "{" ( attribute_spec_commalist )? "}"
tuple_exp_commalist ::= ( expression ( "," expression )* )?
attribute_spec_commalist    ::= attribute_spec ( "," attribute_spec )*
attribute_spec  ::= identifier type_ref
identifier  ::= IDENTIFIER
dereference ::= IDENTIFIER
character   ::= STRING_LITERAL
string_literal  ::= STRING_LITERAL
integer ::= INTEGER_LITERAL
rational    ::= ( FLOATING_POINT_LITERAL | INFINITY | NAN )
bool    ::= TRUE
|   FALSE

//Tokens

//<DEFAULT> TOKEN [IGNORE_CASE] : {
ADD ::= "ADD"
AGGREGATE ::= "AGGREGATE"
AGGREGATED ::= "AGGREGATED"
ALL ::= "ALL"
ALTER ::= "ALTER"
AND ::= "AND"
ANNOUNCE ::= "ANNOUNCE"
ARRAY ::= "ARRAY"
AS ::= "AS"
ASC ::= "ASC"
ATTRIBUTES_OF ::= "ATTRIBUTES_OF"
AVG ::= "AVG"
AVGD ::= "AVGD"
BASE ::= "BASE"
BACKUP ::= "BACKUP"
BEGIN ::= "BEGIN"
BUT ::= "BUT"
BY ::= "BY"
CALL ::= "CALL"
CASE ::= "CASE"
COMMIT ::= "COMMIT"
COMPOSE ::= "COMPOSE"
CONSTRAINT ::= "CONSTRAINT"
COUNT ::= "COUNT"
COUNTD ::= "COUNTD"
DELETE ::= "DELETE"
DESC ::= "DESC"
DISTINCT ::= "DISTINCT"
DIVIDEBY ::= "DIVIDEBY"
DO ::= "DO"
DROP ::= "DROP"
D_INSERT ::= "D_INSERT"
D_UNION ::= "D_UNION"
ELSE ::= "ELSE"
END ::= "END"
EOT ::= "<EOT>"
EQUIV ::= "EQUIV"
EXACTLYD ::= "EXACTLYD"
EXACTLY ::= "EXACTLY"
EXECUTE ::= "EXECUTE"
EXTEND ::= "EXTEND"
EXTERNAL ::= "EXTERNAL"
FALSE ::= "FALSE"
FOREIGN ::= "FOREIGN"
FOR ::= "FOR"
FROM ::= "FROM"
FULL ::= "FULL"
GROUP ::= "GROUP"
I_DELETE ::= "I_DELETE"
I_MINUS ::= "I_MINUS"
IF ::= "IF"
IMAGE_IN ::= "IMAGE_IN"
IN ::= "IN"
INFINITY ::= "INFINITY"
INIT ::= "INIT"
INSERT ::= "INSERT"
INTERSECT ::= "INTERSECT"
IS ::= "IS"
JOIN ::= "JOIN"
KEY ::= "KEY"
LEAVE ::= "LEAVE"
LEFT ::= "LEFT"
LOAD ::= "LOAD"
LAMBDA ::= "~["
LAMBDAEND ::= "]~"
MATCHING ::= "MATCHING"
MAX ::= "MAX"
MIN ::= "MIN"
MINUS ::= "MINUS"
NAN ::= "NAN"
NOEMPTY ::= "NOEMPTY"
NOT ::= "NOT"
OPERATOR ::= "OPERATOR"
ORDER ::= "ORDER"
ORDERED ::= "ORDERED"
ORDINAL ::= "ORDINAL"
OR ::= "OR"
OUTPUT ::= "OUTPUT"
PER ::= "PER"
POSSREP ::= "POSSREP"
PREFIX ::= "PREFIX"
PRIVATE ::= "PRIVATE"
PUBLIC ::= "PUBLIC"
RANK ::= "RANK"
REAL ::= "REAL"
RELATION ::= "RELATION" | "REL"
RENAME ::= "RENAME"
RETURN ::= "RETURN"
RETURNS ::= "RETURNS"
RIGHT ::= "RIGHT"
ROLLBACK ::= "ROLLBACK"
SAME_HEADING_AS ::= "SAME_HEADING_AS"
SAME_TYPE_AS ::= "SAME_TYPE_AS"
SEARCH ::= "SEARCH"
SET ::= "SET"
SEMIJOIN ::= "SEMIJOIN"
SEMIMINUS ::= "SEMIMINUS"
SUFFIX ::= "SUFFIX"
SUMD ::= "SUMD"
SUMMARIZE ::= "SUMMARIZE"
SUM ::= "SUM"
SYNONYMS ::= "SYNONYMS"
TABLE_DEE ::= "DEE" | "TABLE_DEE"
TABLE_DUM ::= "DUM" | "TABLE_DUM"
TCLOSE ::= "TCLOSE"
THEN ::= "THEN"
TIMES ::= "TIMES"
TO ::= "TO"
TRANSACTION ::= "TRANSACTION"
TRUE ::= "TRUE"
TUPLE ::= "TUPLE" | "TUP"
TYPE ::= "TYPE"
TYPE_OF ::= "TYPE_OF"
UNGROUP ::= "UNGROUP"
UNION ::= "UNION"
UNORDER ::= "UNORDER"
UNWRAP ::= "UNWRAP"
UPDATES ::= "UPDATES"
UPDATE ::= "UPDATE"
VAR ::= "VAR"
VERSION ::= "VERSION"
VIRTUAL ::= "VIRTUAL" | "VIEW"
WHEN ::= "WHEN"
WHERE ::= "WHERE"
WHILE ::= "WHILE"
WITH ::= "WITH"
WRAP ::= "WRAP"
WRITE ::= "WRITE"
WRITELN ::= "WRITELN"
XOR ::= "XOR"
XUNION ::= "XUNION"
//}

//<DEFAULT> TOKEN : {
INTEGER_LITERAL ::= DECIMAL_LITERAL (["l","L"])?
//DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])*
FLOATING_POINT_LITERAL ::= (["0"-"9"])+ "." (["0"-"9"])* (EXPONENT)? (["f","F","d","D"])? | "." (["0"-"9"])+ (EXPONENT)? (["f","F","d","D"])? | (["0"-"9"])+ EXPONENT (["f","F","d","D"])? | (["0"-"9"])+ (EXPONENT)? ["f","F","d","D"]
//EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+
//STRING_LITERAL ::= ("\"" | "\u2018" | "\u2019" | "\u201c" | "\u201d") (~["\"","\\","\n","\r"] | "\\" (["n","t","b","r","f","\\","\'","\""] | ["0"-"7"] (["0"-"7"])? | ["0"-"3"] ["0"-"7"] ["0"-"7"]))* ("\"" | "\'" | "\u2018" | "\u2019" | "\u201c" | "\u201d") | "\'" (~["\'","\\","\n","\r"] | "\\" (["n","t","b","r","f","\\","\'","\""] | ["0"-"7"] (["0"-"7"])? | ["0"-"3"] ["0"-"7"] ["0"-"7"]))* ("\'" | "\"" | "\u2018" | "\u2019" | "\u201c" | "\u201d")
//}

//<DEFAULT> TOKEN : {
IDENTIFIER ::= LETTER (LETTER DIGIT | "." | "#")*
//LETTER: ["$","A"-"Z","_","a"-"z","\u00c0"-"\u00d6","\u00d8"-"\u00f6","\u00f8"-"\u00ff","\u0100"-"\u1fff","\u3040"-"\u318f","\u3300"-"\u337f","\u3400"-"\u3d2d","\u4e00"-"\u9fff","\uf900"-"\ufaff"]
//DIGIT: ["0"-"9","\u0660"-"\u0669","\u06f0"-"\u06f9","\u0966"-"\u096f","\u09e6"-"\u09ef","\u0a66"-"\u0a6f","\u0ae6"-"\u0aef","\u0b66"-"\u0b6f","\u0be7"-"\u0bef","\u0c66"-"\u0c6f","\u0ce6"-"\u0cef","\u0d66"-"\u0d6f","\u0e50"-"\u0e59","\u0ed0"-"\u0ed9","\u1040"-"\u1049"]
//}

//<DEFAULT> TOKEN : {
LPAREN ::= "("
RPAREN ::= ")"
LBRACE ::= "{"
RBRACE ::= "}"
SEMICOLON ::= ";"
COMMA ::= ","
COLON ::= ":"
//}

//<DEFAULT> TOKEN : {
ASSIGN ::= ":="
EQ ::= "="
GT ::= ">"
LT ::= "<"
LTE_A ::= "<="
LTE_U ::= "\u2264"
GTE_A ::= ">="
GTE_U ::= "\u2265"
NEQ_A ::= "<>"
NEQ_U ::= "\u2260"
PLUS ::= "+"
SUBT ::= "-"
STAR ::= "*"
MULT_U ::= "\u00d7"
DIVD_A ::= "/"
DIVD_U ::= "\u00f7"
MODL ::= "%"
BANGBANG_A ::= "!!"
BANGBANG_U ::= "\u203c"
SUBSET ::= "\u2282"
SUBSET_OR_EQUAL ::= "\u2286"
SUPERSET ::= "\u2283"
SUPERSET_OR_EQUAL ::= "\u2287"
ELEMENT_U ::= "\u2208"
BARBAR ::= "||"
//}
DaveVoorhis commented 1 year ago

Nice!

On 5 Nov 2022, at 11:41, Domingo Alvarez Duarte @.***> wrote:

After massaging a bit the grammar shown here https://reldb.org/TutorialD.html (basically removing <> and replacing : by ::= we can have an EBNF grammar accepted by https://www.bottlecaps.de/rr/ui to produce a navigable railroad diagram (https://en.wikipedia.org/wiki/Syntax_diagram).

Copy and paste the EBNF shown bellow at https://www.bottlecaps.de/rr/ui on the tab Edit Grammar then switch/click to the tab View Diagram.

evaluate ::= ( compound_statement_body ";" )? expression ( EOT | EOF ) ...

mingodad commented 1 year ago

Better yet is to use the grammar at https://github.com/DaveVoorhis/Rel/blob/master/ServerV0000/src/main/java/org/reldb/rel/v0/languages/tutoriald/definition/TutorialD.jjt after commenting the AST tags and use https://www.bottlecaps.de/convert/ to convert it:

EBNF already converted to be used at https://www.bottlecaps.de/rr/ui:

/* converted on Sat Nov 5, 2022, 13:00 (UTC+01) by javacc-to-w3c v0.61 which is Copyright (c) 2011-2022 by Gunther Rademacher <grd@gmx.net> */

evaluate ::= ( compound_statement_body ';' )? expression ( '<EOT>' | EOF )
statement_list
         ::= statement*
code     ::= statement_list ( '<EOT>' | EOF )
statement
         ::= statement_body ';'
op_before_returns
         ::= 'OPERATOR' identifier '(' ( identifier type_ref ( ',' identifier type_ref )* )? ')'
op_after_returns
         ::= ( op_updates op_synonym op_version ';' op_body 'END' | identifier 'FOREIGN' TEXT* ENDFOREIGN ) 'OPERATOR'?
getoperatorreturntype
         ::= op_before_returns op_returns op_after_returns
getheading
         ::= heading
getsignature
         ::= op_signature op_returns
statement_body
         ::= assignment
           | loop
           | op_def
           | type_def
           | drop
           | alter
           | var_def
           | db_constraint_def
           | relation_array_load
           | begin_transaction
           | compound_statement_body
           | 'COMMIT'
           | 'ROLLBACK'
           | call
           | return_statement
           | case_statement
           | if_statement
           | leave
           | write
           | writeln
           | output
           | announce
           | execute
           | set
           | 'BACKUP'
write    ::= 'WRITE' expression
writeln  ::= 'WRITELN' expression?
output   ::= 'OUTPUT' expression
announce ::= 'ANNOUNCE' string_literal
execute  ::= 'EXECUTE' expression
set      ::= 'SET' identifier identifier
compound_statement_body
         ::= 'BEGIN' ';' statement_list 'END'
op_def   ::= 'OPERATOR' identifier '(' parameter_def_commalist ')' op_returns ( rel_op_def | external_op_def )
lambda   ::= 'OPERATOR' lambda_definition 'END' 'OPERATOR'?
           | '~[' lambda_definition ']~'
lambda_definition
         ::= '(' parameter_def_commalist ')' 'RETURNS' type_ref ';' op_body
external_op_def
         ::= identifier 'FOREIGN' TEXT* ENDFOREIGN 'OPERATOR'?
rel_op_def
         ::= op_updates op_synonym op_version ';' op_body 'END' 'OPERATOR'?
op_returns
         ::= ( 'RETURNS' type_ref )?
op_updates
         ::= ( 'UPDATES' '{' ( 'ALL' 'BUT' parameter_name_commalist )? '}' )?
op_synonym
         ::= synonym_def?
op_version
         ::= ( 'VERSION' identifier )?
op_body  ::= statement_list
return_statement
         ::= 'RETURN' expression?
parameter_def_commalist
         ::= ( parameter_def ( ',' parameter_def )* )?
parameter_def
         ::= identifier type_ref
parameter_name_commalist
         ::= ( identifier ( ',' identifier )* )?
synonym_def
         ::= 'SYNONYMS' '{' user_op_name_commalist '}'
user_op_name_commalist
         ::= identifier ( ',' identifier )*
drop     ::= 'DROP' ( 'OPERATOR' op_signature | ( 'VAR' | 'CONSTRAINT' | 'TYPE' ) identifier )
op_signature
         ::= identifier '(' type_ref_commalist ')'
alter    ::= 'ALTER' alter_var
alter_var
         ::= 'VAR' identifier alter_var_action_optional var_keydeflist?
alter_var_action_optional
         ::= alter_var_action*
alter_var_action
         ::= ( 'RENAME' identifier 'TO' | 'DROP' ) identifier
           | 'TYPE_OF' identifier 'TO' type_ref
           | 'INSERT' attribute_spec
op_type  ::= 'OPERATOR' '(' type_ref_commalist ')' ( 'RETURNS' type_ref )?
type_ref_commalist
         ::= ( type_ref ( ',' type_ref )* )?
type_def ::= 'TYPE' identifier type_def_kind
type_def_kind
         ::= type_def_external
           | type_def_internal
type_def_external
         ::= identifier 'FOREIGN' TEXT* ENDFOREIGN 'TYPE'?
type_def_internal
         ::= type_def_internal_ordinal type_def_internal_union type_def_internal_is_or_possrep
type_def_internal_is_or_possrep
         ::= is_def
           | possrep_def_list
type_def_internal_ordinal
         ::= type_def_internal_opt_ordinal?
type_def_internal_opt_ordinal
         ::= 'ORDINAL'
           | 'ORDERED'
type_def_internal_union
         ::= 'UNION'?
is_def   ::= 'IS' '{' ( single_inheritance_is_def | multiple_inheritance_is_def ) '}'
single_inheritance_is_def
         ::= identifier possrep_or_specialization_details
possrep_or_specialization_details
         ::= specialisation_constraint_def derived_possrep_def_list?
           | possrep_def_list
multiple_inheritance_is_def
         ::= scalar_type_name_commalist derived_possrep_def_list
scalar_type_name_commalist
         ::= scalar_type_name ( ',' scalar_type_name )*
scalar_type_name
         ::= identifier
possrep_def_list
         ::= possrep_def* possrep_opt_initialiser
possrep_opt_initialiser
         ::= ( 'INIT' possrep_initialiser_assignments+ )?
possrep_initialiser_assignments
         ::= identifier '(' assignment ')'
possrep_def
         ::= 'POSSREP' possrep_def_identifier ( '{' | '(' ) possrep_component_def_commalist possrep_opt_constraint_def ( '}' | ')' )
possrep_def_identifier
         ::= identifier?
possrep_opt_constraint_def
         ::= constraint_def?
possrep_component_def_commalist
         ::= ( possrep_component_def ( ',' possrep_component_def )* )?
possrep_component_def
         ::= identifier type_ref
constraint_def
         ::= 'CONSTRAINT' expression
specialisation_constraint_def
         ::= 'CONSTRAINT' expression
derived_possrep_def_list
         ::= derived_possrep_def+
derived_possrep_def
         ::= 'POSSREP' derived_possrep_def_opt_identifier ( '(' | '{' ) derived_possrep_component_def_commalist ( '}' | ')' )
derived_possrep_def_opt_identifier
         ::= identifier?
derived_possrep_component_def_commalist
         ::= derived_possrep_component_def ( ',' derived_possrep_component_def )*
derived_possrep_component_def
         ::= identifier '=' identifier '(' identifier ')'
var_def  ::= 'VAR' identifier ( var_scalar_or_tuple | var_relvar )
var_relvar
         ::= ( ( 'REAL' | 'BASE' | 'PRIVATE' ) var_type_or_init_value | 'PUBLIC' type_ref ) var_keydeflist
           | VIRTUAL expression var_keydeflistoptional
           | var_relvar_external
var_relvar_external
         ::= 'EXTERNAL' identifier string_literal identifier?
var_keydeflist
         ::= var_keydef+
var_keydeflistoptional
         ::= var_keydef*
var_keydef
         ::= 'KEY' '{' attribute_name_list '}'
var_scalar_or_tuple
         ::= var_type_or_init_value
var_type_or_init_value
         ::= var_type_and_optional_init
           | var_init
var_type_and_optional_init
         ::= type_ref ( 'INIT' '(' expression ')' )?
var_init ::= 'INIT' '(' expression ')'
db_constraint_def
         ::= 'CONSTRAINT' identifier expression
type_ref ::= identifier
           | type_same_type_as
           | tuple_type
           | relation_type
           | op_type
           | type_array
type_array
         ::= 'ARRAY' type_ref
type_same_type_as
         ::= 'SAME_TYPE_AS' '(' expression ')'
tuple_type
         ::= TUPLE heading_type
relation_type
         ::= RELATION heading_type
heading_type
         ::= heading
           | same_heading_as
same_heading_as
         ::= 'SAME_HEADING_AS' '(' expression ')'
relation_array_load
         ::= 'LOAD' identifier 'FROM' expression
begin_transaction
         ::= 'BEGIN' 'TRANSACTION'
case_statement
         ::= 'CASE' ';' when_def_list case_else 'END' 'CASE'?
when_def_list
         ::= when_def+
when_def ::= 'WHEN' expression 'THEN' statement_list
case_else
         ::= ( 'ELSE' statement_list )?
if_statement
         ::= 'IF' expression 'THEN' statement_list if_statement_else 'END' 'IF'?
if_statement_else
         ::= ( 'ELSE' statement_list )?
loop     ::= ( identifier ':' )? ( do_statement | while_statement | for_statement )
do_statement
         ::= 'DO' identifier ':=' expression 'TO' expression ';' statement_list 'END' 'DO'?
while_statement
         ::= 'WHILE' expression ';' statement_list 'END' 'WHILE'?
for_statement
         ::= 'FOR' expression ';' statement_list 'END' 'FOR'?
leave    ::= 'LEAVE' identifier
call     ::= 'CALL' identifier '(' arglist ')'
assignment
         ::= assign ( ',' assign )*
assign   ::= ( identifier ':=' | ( 'INSERT' | 'D_INSERT' | 'I_DELETE' ) identifier ) expression
           | 'DELETE' identifier delete_parameter
           | 'UPDATE' identifier update_where ':' update_assignment
delete_parameter
         ::= ( 'WHERE'? expression )?
update_where
         ::= ( 'WHERE' expression )?
update_assignment
         ::= '{' assignment? '}'
expression
         ::= attribute_from
           | basic_expression
           | tuple_from
           | with
           | tclose
attribute_from
         ::= identifier 'FROM' expression
tuple_from
         ::= TUPLE 'FROM' expression
with     ::= 'WITH' '(' name_intro_commalist ')' ':' expression
name_intro_commalist
         ::= name_intro ( ',' name_intro )*
name_intro
         ::= identifier ':=' expression
tclose   ::= 'TCLOSE' expression
basic_expression
         ::= order_expression ( '[' expression ']' | '(' arglist ')' )?
order_expression
         ::= where_expression ( ( 'ORDER' '(' order_item_commalist | 'UNORDER' '(' ) ')' )?
where_expression
         ::= equiv_expression ( 'WHERE' equiv_expression )?
equiv_expression
         ::= or_expression ( 'EQUIV' or_expression )*
or_expression
         ::= xor_expression ( 'OR' xor_expression )*
xor_expression
         ::= and_expression ( 'XOR' and_expression )*
and_expression
         ::= compare_expression ( 'AND' compare_expression )*
compare_expression
         ::= rel_op ( ( '=' | '<>' | NEQ_U | '>=' | GTE_U | '<=' | LTE_U | '>' | '<' | SUBSET | SUBSET_OR_EQUAL | SUPERSET | SUPERSET_OR_EQUAL | 'IN' | ELEMENT_U ) rel_op )?
rel_op   ::= rel_project ( ( 'RENAME' '{' renaming_commalist | 'EXTEND' ':'? '{' extend_add_commalist | 'SUMMARIZE' per_or_by ':'? '{' summarize_add_commalist ) '}' | ( 'RANK' 'BY'? '(' order_item_commalist 'AS' identifier | 'DIVIDEBY' expression 'PER' '(' expression divide_per_optional ) ')' | 'UPDATE' ':'? update_assignment | 'WRAP' wrapping | ( 'UNWRAP' | 'UNGROUP' ) identifier | 'GROUP' grouping | ( 'UNION' | 'XUNION' | 'D_UNION' | 'INTERSECT' | 'MINUS' | 'I_MINUS' | ( 'LEFT' | 'RIGHT' | 'FULL' )? 'JOIN' | 'TIMES' | 'COMPOSE' | 'SEMIJOIN' | 'NOT'? 'MATCHING' | 'SEMIMINUS' ) rel_project )*
order_item_commalist
         ::= ( order_item ( ',' order_item )* )?
order_item
         ::= ( 'ASC' | 'DESC' ) identifier
divide_per_optional
         ::= ( ',' expression )?
grouping ::= '{' attribute_name_list '}' 'AS' identifier
wrapping ::= '{' attribute_name_list '}' 'AS' identifier
renaming_commalist
         ::= ( renaming ( ',' renaming )* )?
renaming ::= renaming_simple
           | renaming_prefix
           | renaming_suffix
renaming_simple
         ::= identifier 'AS' identifier
renaming_prefix
         ::= 'PREFIX' string_literal 'AS' string_literal
renaming_suffix
         ::= 'SUFFIX' string_literal 'AS' string_literal
attribute_name_list
         ::= optional_all_but attribute_name_commalist
optional_all_but
         ::= ( 'ALL' 'BUT' )?
attribute_name_commalist
         ::= attribute_name_commalist_attributes_of
           | attribute_name_commalist_list
attribute_name_commalist_attributes_of
         ::= 'ATTRIBUTES_OF' '(' expression ')'
attribute_name_commalist_list
         ::= ( identifier ( ',' identifier )* )?
rel_project
         ::= add_expression ( '{' attribute_name_list '}' )?
add_expression
         ::= mul_expression ( ( '+' | '-' | '||' ) mul_expression )*
mul_expression
         ::= unary_expression ( ( '*' | MULT_U | '/' | DIVD_U | '%' ) unary_expression )*
unary_expression
         ::= ( 'NOT' | '+' | '-' )* primary_expression
primary_expression
         ::= literal
           | aggregate_operator
           | exactly
           | nadic_or
           | nadic_equiv
           | nadic_xor
           | nadic_and
           | nadic_union
           | nadic_xunion
           | nadic_disjoint_union
           | nadic_intersect
           | nadic_join
           | nadic_times
           | nadic_compose
           | nadic_count
           | nadic_sum
           | nadic_avg
           | nadic_max
           | nadic_min
           | extend
           | rank
           | summarize
           | substitute
           | case_expression
           | if_expression
           | search
           | type_of
           | image_in
           | fn_invoke
           | dereference
           | '(' expression ')'
search   ::= 'SEARCH' '(' expression ',' expression ')'
type_of  ::= 'TYPE_OF' '(' expression ')'
image_in ::= ( '!!' | BANGBANG_U ) ( image_in_bracketed | image_in_identifier )
           | 'IMAGE_IN' image_in_bracketed
image_in_bracketed
         ::= '(' expression ( ',' expression )? ')'
image_in_identifier
         ::= identifier
case_expression
         ::= 'CASE' when_def_list_expr 'ELSE' expression 'END' 'CASE'?
when_def_list_expr
         ::= when_def_expr+
when_def_expr
         ::= 'WHEN' expression 'THEN' expression
if_expression
         ::= 'IF' expression 'THEN' expression 'ELSE' expression 'END' 'IF'?
substitute
         ::= 'UPDATE' expression ':' update_assignment
nadic_optional_heading
         ::= heading? '{' heading_exp_commalist '}'
nadic_union
         ::= 'UNION' nadic_optional_heading
nadic_xunion
         ::= 'XUNION' nadic_optional_heading
nadic_disjoint_union
         ::= 'D_UNION' nadic_optional_heading
nadic_intersect
         ::= 'INTERSECT' nadic_optional_heading
nadic_join
         ::= 'JOIN' '{' heading_exp_commalist '}'
nadic_times
         ::= 'TIMES' '{' heading_exp_commalist '}'
nadic_compose
         ::= 'COMPOSE' '{' heading_exp_commalist '}'
nadic_or ::= 'OR' '{' bool_exp_commalist '}'
nadic_equiv
         ::= 'EQUIV' '{' bool_exp_commalist '}'
nadic_xor
         ::= 'XOR' '{' bool_exp_commalist '}'
nadic_and
         ::= 'AND' '{' bool_exp_commalist '}'
nadic_count
         ::= 'COUNT' '{' exp_commalist '}'
nadic_sum
         ::= 'SUM' '{' exp_commalist '}'
nadic_avg
         ::= 'AVG' '{' exp_commalist '}'
nadic_max
         ::= 'MAX' '{' exp_commalist '}'
nadic_min
         ::= 'MIN' '{' exp_commalist '}'
exactly  ::= 'EXACTLY' '(' expression ( ',' expression )* ')'
exp_commalist
         ::= ( expression ( ',' expression )* )?
bool_exp_commalist
         ::= ( expression ( ',' expression )* )?
heading_exp_commalist
         ::= ( expression ( ',' expression )* )?
extend   ::= 'EXTEND' expression ':' '{' extend_add_commalist '}'
rank     ::= 'RANK' expression 'BY' '(' order_item_commalist 'AS' identifier ')'
extend_add_commalist
         ::= ( extend_add ( ',' extend_add )* )?
extend_add
         ::= identifier ':=' expression
summarize
         ::= 'SUMMARIZE' expression per_or_by ':' '{' summarize_add_commalist '}'
per_or_by
         ::= ( 'PER' '(' expression ')' | 'BY' '{' attribute_name_list '}' )?
summarize_add_commalist
         ::= summarize_add ( ',' summarize_add )*
summarize_add
         ::= identifier ':=' summary
summary  ::= ( 'COUNT' '(' | ( ( 'COUNTD' | 'SUM' | 'SUMD' | 'AVG' | 'AVGD' | 'MAX' | 'MIN' | 'AND' | 'OR' | 'EQUIV' | 'XOR' | 'UNION' | 'XUNION' | 'D_UNION' | 'INTERSECT' ) '(' | ( 'EXACTLY' | 'EXACTLYD' ) '(' expression ',' ) expression ) ')'
           | summarize_aggregate
           | summarize_aggregated
           | summarize_userdefined
summarize_aggregate
         ::= 'AGGREGATE' '(' expression ( ',' expression )? ')' ';' op_body 'END' 'AGGREGATE'?
summarize_aggregated
         ::= 'AGGREGATED' '(' expression ( ',' expression )? ')' ';' op_body 'END' 'AGGREGATED'?
summarize_userdefined
         ::= identifier '(' SummarizeItemDistinct expression ( ',' expression )? ')'
SummarizeItemDistinct
         ::= 'DISTINCT'?
fn_invoke
         ::= identifier '(' arglist ')'
arglist  ::= ( expression ( ',' expression )* )?
aggregate_operator
         ::= ( 'COUNT' '(' | ( 'SUM' | 'AVG' | 'MAX' | 'MIN' | 'AND' | 'OR' | 'EQUIV' | 'XOR' | 'UNION' | 'XUNION' | 'D_UNION' | 'INTERSECT' ) '(' expression ',' ) expression ')'
           | agg_aggregate
agg_aggregate
         ::= 'AGGREGATE' ( agg_aggregate_inline | agg_aggregate_userdefined )
agg_aggregate_inline
         ::= '(' expression ',' expression ( ',' expression )? ')' ';' op_body 'END' 'AGGREGATE'?
agg_aggregate_userdefined
         ::= identifier '(' expression ',' expression ( ',' expression )? ')'
literal  ::= lambda
           | tuple
           | relation
           | integer
           | character
           | rational
           | bool
tuple    ::= TUPLE '{' ( '*' | tuple_component_commalist )? '}'
tuple_component_commalist
         ::= tuple_component ( ',' tuple_component )*
tuple_component
         ::= identifier expression
relation ::= RELATION relation_heading '{' tuple_exp_commalist '}'
           | TABLE_DUM
           | TABLE_DEE
relation_heading
         ::= heading_type?
heading  ::= '{' attribute_spec_commalist? '}'
tuple_exp_commalist
         ::= ( expression ( ',' expression )* )?
attribute_spec_commalist
         ::= attribute_spec ( ',' attribute_spec )*
attribute_spec
         ::= identifier type_ref
identifier
         ::= IDENTIFIER
dereference
         ::= IDENTIFIER
character
         ::= STRING_LITERAL
string_literal
         ::= STRING_LITERAL
integer  ::= INTEGER_LITERAL
rational ::= FLOATING_POINT_LITERAL
           | 'INFINITY'
           | 'NAN'
bool     ::= 'TRUE'
           | 'FALSE'

<?TOKENS?>

SINGLE_LINE_COMMENT
         ::= '//' [^#xA#xD]* ( #xA | #xD #xA? )
FORMAL_COMMENT
         ::= '/**' [^*]* '*' ( ( [^*/] [^*]* )? '*' )* '/'
MULTI_LINE_COMMENT
         ::= '/*' [^*]* '*' ( ( [^*/] [^*]* )? '*' )* '/'
RELATION ::= 'RELATION'
           | 'REL'
TABLE_DEE
         ::= 'DEE'
           | 'TABLE_DEE'
TABLE_DUM
         ::= 'DUM'
           | 'TABLE_DUM'
TUPLE    ::= 'TUPLE'
           | 'TUP'
VIRTUAL  ::= 'VIRTUAL'
           | 'VIEW'
INTEGER_LITERAL
         ::= DECIMAL_LITERAL [lL]?
DECIMAL_LITERAL
         ::= [0-9]+
FLOATING_POINT_LITERAL
         ::= [0-9]+ ( ( '.' [0-9]* EXPONENT? | EXPONENT ) [fFdD]? | EXPONENT? [fFdD] )
           | '.' [0-9]+ EXPONENT? [fFdD]?
EXPONENT ::= [eE] [+#x2D]? [0-9]+
STRING_LITERAL
         ::= ["#x2018#x2019#x201C#x201D] ( [^"\#xA#xD] | '\' ( [ntbrf\'"] | ( [0-3]? [0-7] )? [0-7] ) )* ["'#x2018#x2019#x201C#x201D]
           | "'" ( [^'\#xA#xD] | '\' ( [ntbrf\'"] | ( [0-3]? [0-7] )? [0-7] ) )* ['"#x2018#x2019#x201C#x201D]
IDENTIFIER
         ::= LETTER ( LETTER | DIGIT | '.' | '#' )*
LETTER   ::= [$A-Z_a-z#xC0-#xD6#xD8-#xF6#xF8-#xFF#x100-#x1FFF#x3040-#x318F#x3300-#x337F#x3400-#x3D2D#x4E00-#x9FFF#xF900-#xFAFF]
DIGIT    ::= [0-9#x660-#x669#x6F0-#x6F9#x966-#x96F#x9E6-#x9EF#xA66-#xA6F#xAE6-#xAEF#xB66-#xB6F#xBE7-#xBEF#xC66-#xC6F#xCE6-#xCEF#xD66-#xD6F#xE50-#xE59#xED0-#xED9#x1040-#x1049]
LTE_U    ::= #x2264
GTE_U    ::= #x2265
NEQ_U    ::= #x2260
MULT_U   ::= #xD7
DIVD_U   ::= #xF7
BANGBANG_U
         ::= #x203C
SUBSET   ::= #x2282
SUBSET_OR_EQUAL
         ::= #x2286
SUPERSET ::= #x2283
SUPERSET_OR_EQUAL
         ::= #x2287
ELEMENT_U
         ::= #x2208
ENDFOREIGN
         ::= #xA 'END'
TEXT     ::= .
EOF      ::= $

TutorialD.jjt with AST tags commented to use at https://www.bottlecaps.de/convert/:

/*
 * Rel implementation of Tutorial D from TTM 3rd Edition
 *
 */

options {
  LOOKAHEAD = 1;
  CHOICE_AMBIGUITY_CHECK = 2;
  OTHER_AMBIGUITY_CHECK = 1;
  STATIC = false;
  DEBUG_PARSER = false;
  DEBUG_LOOKAHEAD = false;
  DEBUG_TOKEN_MANAGER = false;
  ERROR_REPORTING = true;
  JAVA_UNICODE_ESCAPE = true;
  UNICODE_INPUT = true;
  IGNORE_CASE = false;
  USER_TOKEN_MANAGER = false;
  USER_CHAR_STREAM = false;
  BUILD_PARSER = true;
  BUILD_TOKEN_MANAGER = true;
  SANITY_CHECK = true;
  FORCE_LA_CHECK = false;
  MULTI = true;
  NODE_SCOPE_HOOK = true;
  VISITOR = true;
  NODE_DEFAULT_VOID = true;
  NODE_EXTENDS = "org.reldb.rel.v0.languages.tutoriald.BaseASTNode";
  NODE_PACKAGE = "org.reldb.rel.v0.languages.tutoriald.parser";
  JDK_VERSION = "1.8";
}

PARSER_BEGIN(TutorialD)
package org.reldb.rel.v0.languages.tutoriald.parser;

@SuppressWarnings("all")
public class TutorialD {
  void jjtreeOpenNodeScope( Node node )
  {
    ((org.reldb.rel.v0.languages.tutoriald.BaseASTNode)node).first_token = getToken(1);
  }

  void jjtreeCloseNodeScope( Node node )
  {
    ((org.reldb.rel.v0.languages.tutoriald.BaseASTNode)node).last_token = getToken(0);
  }

  public void setTabSize(int size) {
       jj_input_stream.setTabSize(size);
  }

  public int getTabSize() {
       return jj_input_stream.getTabSize();
  }
}
PARSER_END(TutorialD)

/*
 *
 * Lexer definitions
 *
 */

SKIP : /* WHITE SPACE */
{
  " "
| "\t"
| "\n"
| "\r"
| "\f"
}

SPECIAL_TOKEN : /* COMMENTS */
{
  <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
| <FORMAL_COMMENT: "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
| <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
}

TOKEN [IGNORE_CASE] : /* RESERVED WORDS AND LITERALS */
{
  < ADD: "ADD" >
| < AGGREGATE: "AGGREGATE" >
| < AGGREGATED: "AGGREGATED" >
| < ALL: "ALL" >
| < ALTER: "ALTER" >
| < AND: "AND" >
| < ANNOUNCE: "ANNOUNCE" >
| < ARRAY: "ARRAY" >
| < AS: "AS" >
| < ASC: "ASC" >
| < ATTRIBUTES_OF: "ATTRIBUTES_OF" >
| < AVG: "AVG" >
| < AVGD: "AVGD" >
| < BASE: "BASE" >
| < BACKUP: "BACKUP" >
| < BEGIN: "BEGIN" >
| < BUT: "BUT" >
| < BY: "BY" >
| < CALL: "CALL" >
| < CASE: "CASE" >
| < COMMIT: "COMMIT" >
| < COMPOSE: "COMPOSE" >
| < CONSTRAINT: "CONSTRAINT" >
| < COUNT: "COUNT" >
| < COUNTD: "COUNTD" >
| < DELETE: "DELETE" >
| < DESC: "DESC" >
| < DISTINCT: "DISTINCT" >
| < DIVIDEBY: "DIVIDEBY" >
| < DO: "DO" >
| < DROP: "DROP" >
| < D_INSERT: "D_INSERT" >
| < D_UNION: "D_UNION" >
| < ELSE: "ELSE" >
| < END: "END" >
| < EOT: "<EOT>" >
| < EQUIV: "EQUIV" >
| < EXACTLYD: "EXACTLYD" >
| < EXACTLY: "EXACTLY" >
| < EXECUTE: "EXECUTE" >
| < EXTEND: "EXTEND" >
| < EXTERNAL: "EXTERNAL" >
| < FALSE: "FALSE" >
| < FOREIGN: "FOREIGN" >: SCRIPT
| < FOR: "FOR" >
| < FROM: "FROM" >
| < FULL: "FULL" >
| < GROUP: "GROUP" >
| < I_DELETE: "I_DELETE" >
| < I_MINUS: "I_MINUS" >
| < IF: "IF" >
| < IMAGE_IN: "IMAGE_IN" >
| < IN: "IN" >
| < INFINITY: "INFINITY" >
| < INIT: "INIT" >
| < INSERT: "INSERT" >
| < INTERSECT: "INTERSECT" >
| < IS: "IS" >
| < JOIN: "JOIN" >
| < KEY: "KEY" >
| < LEAVE: "LEAVE" >
| < LEFT: "LEFT" >
| < LOAD: "LOAD" >
| < LAMBDA: "~[" >
| < LAMBDAEND: "]~" >
| < MATCHING: "MATCHING" >
| < MAX: "MAX" >
| < MIN: "MIN" >
| < MINUS: "MINUS" >
| < NAN: "NAN" >
| < NOEMPTY: "NOEMPTY" >
| < NOT: "NOT" >
| < OPERATOR: "OPERATOR" >
| < ORDER: "ORDER" >
| < ORDERED: "ORDERED" >
| < ORDINAL: "ORDINAL" >
| < OR: "OR" >
| < OUTPUT: "OUTPUT" >
| < PER: "PER" >
| < POSSREP: "POSSREP" >
| < PREFIX: "PREFIX" >
| < PRIVATE: "PRIVATE" >
| < PUBLIC: "PUBLIC" >
| < RANK: "RANK" >
| < REAL: "REAL" >
| < RELATION: ( "RELATION" | "REL" ) >
| < RENAME: "RENAME" >
| < RETURN: "RETURN" >
| < RETURNS: "RETURNS" >
| < RIGHT: "RIGHT" >
| < ROLLBACK: "ROLLBACK" >
| < SAME_HEADING_AS: "SAME_HEADING_AS" >
| < SAME_TYPE_AS: "SAME_TYPE_AS" >
| < SEARCH: "SEARCH" >
| < SET: "SET" >
| < SEMIJOIN: "SEMIJOIN" > 
| < SEMIMINUS: "SEMIMINUS" >
| < SUFFIX: "SUFFIX" >
| < SUMD: "SUMD" >
| < SUMMARIZE: "SUMMARIZE" >
| < SUM: "SUM" >
| < SYNONYMS: "SYNONYMS" >
| < TABLE_DEE: ( "DEE" | "TABLE_DEE" ) >
| < TABLE_DUM: ( "DUM" | "TABLE_DUM" ) >
| < TCLOSE: "TCLOSE" >
| < THEN: "THEN" >
| < TIMES: "TIMES" >
| < TO: "TO" >
| < TRANSACTION: "TRANSACTION" >
| < TRUE: "TRUE" >
| < TUPLE: ( "TUPLE" | "TUP" ) >
| < TYPE: "TYPE" >
| < TYPE_OF: "TYPE_OF" >
| < UNGROUP: "UNGROUP" >
| < UNION: "UNION" >
| < UNORDER: "UNORDER" >
| < UNWRAP: "UNWRAP" >
| < UPDATES: "UPDATES" >
| < UPDATE: "UPDATE" >
| < VAR: "VAR" >
| < VERSION: "VERSION" >
| < VIRTUAL: ( "VIRTUAL" | "VIEW" ) >
| < WHEN: "WHEN" >
| < WHERE: "WHERE" >
| < WHILE: "WHILE" >
| < WITH: "WITH" >
| < WRAP: "WRAP" >
| < WRITE: "WRITE" >
| < WRITELN: "WRITELN" >
| < XOR: "XOR" >
| < XUNION: "XUNION" >
}

TOKEN : /* LITERALS */
{
  < INTEGER_LITERAL:
        <DECIMAL_LITERAL> (["l","L"])?
  >
|
  < #DECIMAL_LITERAL: ["0"-"9"] (["0"-"9"])* >
|
  < FLOATING_POINT_LITERAL:
        (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
      | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
      | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
      | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
  >
|
  < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
|
  < STRING_LITERAL:
     ( 
      (
        "\""
      | "‘"
      | "’"
      | "“"
      | "”"
      )
      (   (~["\"","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
      )*
      (
        "\""
      | "'"
      | "‘"
      | "’"
      | "“"
      | "”"
      )
     )
   | (
      "'"
      (   (~["\'","\\","\n","\r"])
        | ("\\"
            ( ["n","t","b","r","f","\\","'","\""]
            | ["0"-"7"] ( ["0"-"7"] )?
            | ["0"-"3"] ["0"-"7"] ["0"-"7"]
            )
          )
      )*
      (
        "'"
      | "\""
      | "‘"
      | "’"
      | "“"
      | "”"
      )
     )
  >
}

TOKEN : /* IDENTIFIERS */
{
  < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>|"."|"#")* >
|
  < #LETTER:
      [
       "\u0024",
       "\u0041"-"\u005a",
       "\u005f",
       "\u0061"-"\u007a",
       "\u00c0"-"\u00d6",
       "\u00d8"-"\u00f6",
       "\u00f8"-"\u00ff",
       "\u0100"-"\u1fff",
       "\u3040"-"\u318f",
       "\u3300"-"\u337f",
       "\u3400"-"\u3d2d",
       "\u4e00"-"\u9fff",
       "\uf900"-"\ufaff"
      ]
  >
|
  < #DIGIT:
      [
       "\u0030"-"\u0039",
       "\u0660"-"\u0669",
       "\u06f0"-"\u06f9",
       "\u0966"-"\u096f",
       "\u09e6"-"\u09ef",
       "\u0a66"-"\u0a6f",
       "\u0ae6"-"\u0aef",
       "\u0b66"-"\u0b6f",
       "\u0be7"-"\u0bef",
       "\u0c66"-"\u0c6f",
       "\u0ce6"-"\u0cef",
       "\u0d66"-"\u0d6f",
       "\u0e50"-"\u0e59",
       "\u0ed0"-"\u0ed9",
       "\u1040"-"\u1049"
      ]
  >
}

TOKEN : /* SEPARATORS */
{
  < LPAREN: "(" >
| < RPAREN: ")" >
| < LBRACE: "{" >
| < RBRACE: "}" >
| < SEMICOLON: ";" >
| < COMMA: "," >
| < COLON: ":" >
}

TOKEN : /* OPERATOR SYMBOLS */
{
  < ASSIGN: ":=" >
| < EQ: "=" >
| < GT: ">" >
| < LT: "<" >
| < LTE_A: "<=" >
| < LTE_U: "\u2264" >
| < GTE_A: ">=" >
| < GTE_U: "\u2265" >
| < NEQ_A: "<>" >
| < NEQ_U: "\u2260" >
| < PLUS: "+" >
| < SUBT: "-" >
| < STAR: "*" >
| < MULT_U: "\u00D7" >
| < DIVD_A: "/" >
| < DIVD_U: "\u00F7" >
| < MODL: "%" >
| < BANGBANG_A: "!!" >
| < BANGBANG_U: "\u203C" >
| < SUBSET: "\u2282" >
| < SUBSET_OR_EQUAL: "\u2286" >
| < SUPERSET: "\u2283" >
| < SUPERSET_OR_EQUAL: "\u2287" >
| < ELEMENT_U: "\u2208" >
| < BARBAR: "||" >
}

<SCRIPT> TOKEN: /* Source code grabber */
{
    < ENDFOREIGN : "\nEND" >: DEFAULT
|   < TEXT : ~[] >
}

ASTEvaluate evaluate() /*#Evaluate*/ :
{}
{
    [ compound_statement_body() ";" ] expression() ( <EOT> | <EOF> ) {return jjtThis;}
}

void statement_list() /*#StatementList*/ :
{}
{
    ( statement() )*
}

ASTCode code() /*#Code*/ :
{}
{
    statement_list() ( <EOT> | <EOF> ) {return jjtThis;}
}

ASTStatement statement() /*#Statement*/ :
{}
{
    statement_body() ";" {return jjtThis;}
}

void op_before_returns() :
{}
{
    <OPERATOR> identifier() "(" [ identifier() type_ref() ( "," identifier() type_ref() )* ] ")"
}

void op_after_returns() :
{}
{
            op_updates() op_synonym() op_version() ";" op_body() <END> [ <OPERATOR> ]
      |     identifier() <FOREIGN> ( <TEXT> )* <ENDFOREIGN> [ <OPERATOR> ]
}

ASTGetOperatorReturnType getoperatorreturntype() /*#GetOperatorReturnType(3)*/ :
{}
{
    op_before_returns() op_returns() op_after_returns() {return jjtThis;}
}

ASTGetHeading getheading() /*#GetHeading*/ :
{}
{
    heading() {return jjtThis;}
}

ASTGetSignature getsignature() /*#GetSignature*/ :
{}
{
    op_signature() op_returns() {return jjtThis;}
}

void statement_body() :
{}
{       LOOKAHEAD(2) assignment() | loop()
    |   op_def()
    |   type_def()
    |   drop()
    |   alter()
    |   var_def()
    |   db_constraint_def()
    |   relation_array_load()
    |   LOOKAHEAD(2) begin_transaction() | compound_statement_body()
    |   commit()
    |   rollback()
    |   call()
    |   return_statement()
    |   case_statement()
    |   if_statement()
    |   leave()
    |   write()
    |   writeln()
    |   output()
    |   announce()
    |   execute()
    |   set()
    |   backup()
}

/* Rel extension - non-TTM */
void backup() /*#Backup*/ :
{}
{
  <BACKUP>
}

/* Rel extension - non-TTM */
void write() /*#Write*/ :
{}
{
    <WRITE> expression()
}

/* Rel extension - non-TTM */
void writeln() /*#Writeln*/ :
{}
{
    <WRITELN> [ expression() ]
}

/* Rel extension - non-TTM */
void output() /*#Output*/ :
{}
{
    <OUTPUT> expression()
}

/* Rel extension - non-TTM */
void announce() /*#Announce*/ :
{}
{
    <ANNOUNCE> string_literal()
}

/* Rel extension - non-TTM */ 
void execute() /*#Execute*/ :
{}
{
    <EXECUTE> expression()
}

/* Rel extension - non-TTM */
void set() /*#Set*/ :
{}
{
    <SET> identifier() identifier()
}

void compound_statement_body() :
{}
{
    <BEGIN> ";"
        statement_list()
    <END>
}

void op_def() :
{}
{
    <OPERATOR> identifier() "(" parameter_def_commalist() ")" op_returns() ( rel_op_def() | external_op_def() )
}

void lambda() :
{}
{
    <OPERATOR> lambda_definition() <END> [ <OPERATOR> ]
  | <LAMBDA> lambda_definition() <LAMBDAEND>
}

void lambda_definition() /*#Lambda*/ :
{}
{
   "(" parameter_def_commalist() ")" <RETURNS> type_ref() ";" op_body()
}

void external_op_def() /*#ExternalOpDef(4)*/ :
{Token t; StringBuffer s = new StringBuffer();}
{
    identifier() <FOREIGN> ( t = <TEXT> {s.append(t.toString());} )* {jjtThis.tokenValue = s.toString();} <ENDFOREIGN> [ <OPERATOR> ]
}

void rel_op_def() /*#UserOpDef(7)*/ :
{}
{
    op_updates() op_synonym() op_version() ";"
    op_body()
    <END> [ <OPERATOR> ]
}

/* Note: op_returns() and op_updates()
should be mutually exclusive. */
void op_returns() /*#UserOpReturns*/ :
{}
{
    [ <RETURNS> type_ref() ]
}

void op_updates() /*#UserOpUpdates*/ :
{}
{
    [ <UPDATES> "{" [ <ALL> <BUT> parameter_name_commalist() ] "}" ]
}

void op_synonym() /*#UserOpSynonym*/ :
{}
{
    [ synonym_def() ]
}

void op_version() /*#UserOpVersion*/ :
{}
{
    [ <VERSION> identifier() ]
}

void op_body() /*#UserOpBody*/ :
{}
{
    statement_list()
}

void return_statement() /*#ReturnExpression*/ :
{}
{
    <RETURN> [ expression() ]
}   

/* Not explicitly defined in TTM3 */
void parameter_def_commalist() /*#UserOpParameters*/ :
{}
{
    [ parameter_def() ( "," parameter_def() )* ]
}

void parameter_def() /*#ParmDef*/ :
{}
{
    identifier() type_ref()
}

/* Not explicitly defined in TTM3 */
void parameter_name_commalist() :
{}
{
    [ identifier() ( "," identifier() )* ]
}

void synonym_def() :
{}
{
    <SYNONYMS> "{" user_op_name_commalist() "}"
}

/* Not explicitly defined in TTM3 */
void user_op_name_commalist() :
{}
{
    identifier() ( "," identifier() )*
}

/* Inclusion of type_ref_commalist() in
OPERATOR DROP is not per TTM3,
but necessary to 
disambiguate operators. */
void drop() :
{}
{
    <DROP> 
    (
            <OPERATOR> op_signature()                                   //#DropOperator
        |   <VAR> identifier()                                          //#DropRelvar(1)
        |   <CONSTRAINT> identifier()                                   //#DropConstraint(1)
        |   <TYPE> identifier()                                         //#DropType(1)
    )
}

void op_signature() /*#OpSignature*/ :
{}
{
    identifier() "(" type_ref_commalist() ")"
}

void alter() :
{}
{
  <ALTER> alter_var()
}

void alter_var() /*#AlterVar*/ :
{}
{
  <VAR> identifier() alter_var_action_optional() [ var_keydeflist() /*#AlterVarActionKey()*/ ]
}

void alter_var_action_optional() /*#AlterVarActionOptional*/ :
{ }
{
    ( alter_var_action() )*
}

void alter_var_action() :
{}
{
  <RENAME> identifier() <TO> identifier()               //#AlterVarActionRename(2)
| <TYPE_OF> identifier() <TO> type_ref()                //#AlterVarActionChangeType(2)
| <INSERT> attribute_spec()                             //#AlterVarActionInsert(1)
| <DROP> identifier()                                   //#AlterVarActionDrop(1)
}

void op_type() /*#OpType*/ :
{}
{
    <OPERATOR> "(" type_ref_commalist() ")" [ <RETURNS> type_ref() ]
}

void type_ref_commalist() /*#TypeRefCommalist*/ :
{}
{
    [ type_ref() ( "," type_ref() )* ]
}

/* Was user_scalar_type_def */
void type_def() /*#TypeDef*/ :
{}
{
    <TYPE> identifier() type_def_kind()
}

void type_def_kind() :
{}
{
        LOOKAHEAD(type_def_external())  type_def_external()
    |                                   type_def_internal() 
}

void type_def_external() /*#TypeDefExternal*/ :
{Token t; StringBuffer s = new StringBuffer();}
{
    identifier() <FOREIGN> ( t = <TEXT> {s.append(t.toString());} )* {jjtThis.tokenValue = s.toString();} <ENDFOREIGN> [ <TYPE> ]
}

/* User-defined (internal) types start here */

void type_def_internal() /*#TypeDefInternal*/ :
{}
{
    type_def_internal_ordinal() type_def_internal_union() type_def_internal_is_or_possrep()
}

void type_def_internal_is_or_possrep() :
{}
{
       is_def() 
    |  possrep_def_list()
}

void type_def_internal_ordinal() :
{}
{
    [ type_def_internal_opt_ordinal() ]
}

void type_def_internal_opt_ordinal() :
{}
{
    (
      <ORDINAL> //#TypeDefInternalOptOrdinal 
    | <ORDERED> //#TypeDefInternalOptOrdered
    )
}

void type_def_internal_union() :
{}
{
    [ type_def_internal_opt_union() ]
}

void type_def_internal_opt_union() /*#TypeDefInternalOptUnion*/ :
{}
{
    <UNION>
}

void is_def() :
{}
{
    <IS> "{"
    (
        LOOKAHEAD(2) single_inheritance_is_def() | multiple_inheritance_is_def()
    )
    "}"
}

void single_inheritance_is_def() /*#SingleInheritanceIsDef*/ :
{}
{
    identifier() possrep_or_specialization_details()
}

void possrep_or_specialization_details() :
{}
{
        specialisation_constraint_def() [ derived_possrep_def_list() ]
    |   possrep_def_list()
}

void multiple_inheritance_is_def() /*#MultipleInheritanceIsDef*/ :
{}
{
    scalar_type_name_commalist() derived_possrep_def_list()
}

/* Not explicitly defined in TTM3 */
void scalar_type_name_commalist() :
{}
{
    scalar_type_name() ( "," scalar_type_name() )* 
}

void scalar_type_name() /*#ScalarTypeName*/ :
{}
{
    identifier()
}

/* Not explicitly defined in TTM3 */
void possrep_def_list() :
{}
{
    ( possrep_def() )* possrep_opt_initialiser()
}

/* Not defined in TTM3.  For explicitly setting
values of components not in the current possrep.  
Only required by types with multiple possreps.
Takes the place of "highly protected
operators not part of D". (pg 382, etc.) */
void possrep_opt_initialiser() /*#PossrepInitialiser*/ :
{}
{
    [ <INIT> possrep_initialiser_assignments() ( possrep_initialiser_assignments() )* ]
}

/* Not defined in TTM3, as per above.
Identifier should be existing POSSREP name. */
void possrep_initialiser_assignments() /*#PossrepInitialiserAssignments*/ :
{}
{
    identifier() "(" assignment() ")"
}

void possrep_def() /*#PossrepDef*/ :
{}
{
    <POSSREP> possrep_def_identifier() ("{" | "(") possrep_component_def_commalist() possrep_opt_constraint_def() ("}" | ")")
}

void possrep_def_identifier() /*#PossrepDefIdentifier*/ :
{}
{
    [ identifier() ]
}

void possrep_opt_constraint_def() /*#PossrepDefConstraintDef*/ :
{}
{
    [ constraint_def() ]
}

/* Not explicitly defined in TTM3 */
void possrep_component_def_commalist() /*#PossrepDefComponentCommalist*/ :
{}
{
    [ possrep_component_def() ( "," possrep_component_def() )* ]
}

void possrep_component_def() /*#PossrepDefComponent*/ :
{}
{
    identifier() type_ref()
}

/* Expression must be boolean */
void constraint_def() /*#PossrepConstraintDef*/ :
{}
{
    <CONSTRAINT> expression()
}

/* Expression must be boolean */ 
void specialisation_constraint_def() /*#SpecialisationConstraintDef*/ :
{}
{
    <CONSTRAINT> expression()
}

/* Not explicitly defined in TTM3 */
void derived_possrep_def_list() :
{}
{
    derived_possrep_def() ( derived_possrep_def() )*
}

void derived_possrep_def() /*#DerivedPossrepDef*/ :
{}
{
    <POSSREP> derived_possrep_def_opt_identifier() ("(" | "{") derived_possrep_component_def_commalist() ("}" | ")")
}

void derived_possrep_def_opt_identifier() /*#DerivedPossrepDefOptIdentifier*/ :
{}
{
    [ identifier() ]    
}

/* Not explicitly defined in TTM3 */
void derived_possrep_component_def_commalist() :
{}
{
    derived_possrep_component_def() ( "," derived_possrep_component_def() )*
}

void derived_possrep_component_def() /*#DerivedPossrepComponentDef*/ :
{}
{
    identifier() "=" identifier() "(" identifier() ")"
}

/* End user-defined types (internal) */

/* Includes scalar_var_def,
relation_var_def,
tuple_var_def */
void var_def() /*#VarDef*/ :
{}
{
    <VAR> identifier() 
    (
            var_scalar_or_tuple()
        |   var_relvar()
    )
}

void var_relvar() :
{}
{
        ( <REAL> | <BASE> ) var_type_or_init_value() var_keydeflist()       //#VarRelvarReal(2)
    |   <PRIVATE>           var_type_or_init_value() var_keydeflist()       //#VarRelvarPrivate(2)
    |   <PUBLIC>            type_ref() var_keydeflist()                     //#VarRelvarPublic(2)
    |   <VIRTUAL>           expression() var_keydeflistoptional()           //#VarRelvarVirtual(2)
    |   var_relvar_external()
}

void var_relvar_external() /*#VarRelvarExternal*/ :
{}
{
        <EXTERNAL>  identifier() string_literal() [ identifier() ]
}

void var_keydeflist() /*#KeyDefList*/ :
{}
{
    var_keydef() ( var_keydef() )*
}

void var_keydeflistoptional() /*#KeyDefList*/ :
{}
{
    ( var_keydef() )*
}

void var_keydef() /*#KeyDef*/ :
{}
{
    <KEY> "{" attribute_name_list() "}"
}

void var_scalar_or_tuple() /*#VarScalarOrTuple*/ : 
{}
{
    var_type_or_init_value()
}

void var_type_or_init_value() :
{}
{
        var_type_and_optional_init()
    |   var_init()
}

void var_type_and_optional_init() /*#VarTypeAndOptionalInit*/ :
{}
{
    type_ref() [ <INIT> "(" expression() ")" ]
}

void var_init() /*#VarInit*/ :
{}
{
    <INIT> "(" expression() ")"
}

void db_constraint_def() /*#DatabaseConstraint*/ :
{}
{
    <CONSTRAINT> identifier() expression()
}

/* type -- scalar_type, tuple_type, relation_type */
void type_ref() :
{}
{
        identifier()                            //#Type
    |   type_same_type_as()
    |   tuple_type()
    |   relation_type()
    |   op_type()
    |   type_array()
}

void type_array() /*#TypeArray*/ :
{}
{
    <ARRAY> type_ref()
}

void type_same_type_as() /*#TypeSameTypeAs*/ :
{}
{
    <SAME_TYPE_AS> "(" expression() ")"
}

void tuple_type() /*#TypeTuple*/ :
{}
{
    <TUPLE> heading_type()
}

void relation_type() /*#TypeRelation*/ :
{}
{
    <RELATION> heading_type()
}

void heading_type() :
{}
{
        heading()
    |   same_heading_as()
}

void same_heading_as() /*#SameHeadingAs*/ :
{}
{
    <SAME_HEADING_AS> "(" expression() ")"
}

void relation_array_load() /*#RelationArrayLoad*/ :
{}
{
    <LOAD> identifier() <FROM> expression()
}

void begin_transaction() /*#TransactionBegin*/ :
{}
{
    <BEGIN> <TRANSACTION>
}

void commit() /*#TransactionCommit*/ :
{}
{
    <COMMIT>
}

void rollback() /*#TransactionRollback*/ :
{}
{
    <ROLLBACK>
}

void case_statement() /*#CaseStatement*/ :
{}
{
    <CASE> ";" 
    when_def_list() 
    case_else() 
    <END> [ <CASE> ]
}

void when_def_list() /*#CaseWhenList*/ :
{}
{
    when_def() ( when_def() )*
}

void when_def() /*#CaseWhen*/ :
{}
{
    <WHEN> expression() <THEN> statement_list()
}

void case_else() /*#CaseElse*/ :
{}
{
    [ <ELSE> statement_list() ]
}

/* Note that THEN and ELSE are not
followed by semicolons, but maybe should be? */
void if_statement() /*#IfStatement*/ :
{}
{
    <IF> expression() <THEN> statement_list() 
    if_statement_else()
    <END> [ <IF> ]
}

void if_statement_else() /*#ElseStatement*/ :
{}
{
    [ <ELSE> statement_list() ] 
}

void loop() :
{}
{
    [ identifier() ":" ] ( do_statement() | while_statement() | for_statement() )
}

void do_statement() /*#DoLoop*/ :
{}
{
    <DO> identifier() ":=" expression() <TO> expression() ";"
        statement_list()
    <END> [ <DO> ]
}

void while_statement() /*#WhileLoop*/ :
{}
{
    <WHILE> expression() ";"
        statement_list()
    <END> [ <WHILE> ]
}

void for_statement() /*#ForLoop*/ :
{}
{
    <FOR> expression() ";"
        statement_list()
    <END> [ <FOR> ]
}

void leave() :
{}
{
    <LEAVE> identifier()
}

void call() /*#Call*/ :
{}
{
    <CALL> identifier() "(" arglist() ")"
}

void assignment() /*#Assignment*/ :
{}
{
    assign() ( "," assign() )*
}

void assign() :
{}
{
        identifier() ":=" expression()                                  //#Assign(2)
    |   <INSERT> identifier() expression()                              //#Insert(2)
    |   <D_INSERT> identifier() expression()                            //#DInsert(2)
    |   <DELETE> identifier() delete_parameter()                        //#Delete(2)
    |   <I_DELETE> identifier() expression()                            //#IDelete(2)
    |   <UPDATE> identifier() update_where() ":" update_assignment()    //#UpdateStatement(3)
}

void delete_parameter() /*#DeleteParameter*/ :
{}
{
    [ [ <WHERE> /*#DeleteWhere*/ ] expression() ]
}

void update_where() /*#UpdateWhere*/ :
{}
{
    [ <WHERE> expression() ]
}

void update_assignment() /*#UpdateAssignment*/ :
{}
{
    "{" [ assignment() ] "}"
}

/* Expressions */

void expression() /*#Expression*/ :
{}
{
        LOOKAHEAD(2) attribute_from() 
    |   LOOKAHEAD(2) basic_expression() 
    |   tuple_from()
    |   with()
    |   tclose()
}

void attribute_from() /*#AttributeFrom*/ :
{}
{
    identifier() <FROM> expression()
}

void tuple_from() /*#TupleFrom*/ :
{}
{
    <TUPLE> <FROM> expression()
}

void with() /*#With*/ :
{}
{
    <WITH> "(" name_intro_commalist() ")" ":" expression()
}

void name_intro_commalist() /*#WithNameIntroCommalist*/ :
{}
{
    name_intro() ( "," name_intro() )*
}

void name_intro() :
{}
{
    identifier() ":=" expression()              //#WithNameIntro(2)
}

void tclose() /*#TClose*/ :
{}
{
    <TCLOSE> expression()
}

void basic_expression() :
{}
{
    order_expression()
    [
                        "[" expression() "]"    //#ArrayDereference(2)
        |               "(" arglist() ")"       //#FnInvokeAnonymous(2)
    ]
}

void order_expression() :
{}
{
    where_expression() [ (
      <ORDER> "(" order_item_commalist() ")"    //#AlgOrder(2)
    | <UNORDER> "(" ")"                         //#AlgUnorder(1)
    ) ]     
}

void where_expression() :
{}
{
    equiv_expression() [ <WHERE> equiv_expression() /*#AlgWhere(2)*/ ]
}

void equiv_expression() :
{}
{
    or_expression() ( <EQUIV> or_expression() /*#Equiv(2)*/ )*
}

void or_expression() : 
{} 
{ 
    xor_expression() ( <OR> xor_expression() /*#Or(2)*/ )* 
}

void xor_expression() :
{}
{
    and_expression() ( <XOR> and_expression() /*#Xor(2)*/ )* 
}

void and_expression() : 
{} 
{ 
    compare_expression() ( <AND> compare_expression() /*#And(2)*/ )*
}

void compare_expression() : 
{} 
{ 
    rel_op() [
            <EQ>                    rel_op() //#CompEqual(2)
        |   (<NEQ_A> | <NEQ_U>)     rel_op() //#CompNequal(2)
        |   (<GTE_A> | <GTE_U>)     rel_op() //#CompGTE(2)
        |   (<LTE_A> | <LTE_U>)     rel_op() //#CompLTE(2)
        |   <GT>                    rel_op() //#CompGT(2)
        |   <LT>                    rel_op() //#CompLT(2)
        |   <SUBSET>                rel_op() //#CompSubset(2)
        |   <SUBSET_OR_EQUAL>       rel_op() //#CompSubsetEqual(2)
        |   <SUPERSET>              rel_op() //#CompSuperset(2)
        |   <SUPERSET_OR_EQUAL>     rel_op() //#CompSupersetEqual(2)
        |   (<IN> | <ELEMENT_U >)   rel_op() //#TupleIn(2)
    ]
}

/* Parentheses around  WRAP, UNWRAP, GROUP, UNGROUP removed as of 1.0.11
   Infix EXTEND added as of 1.0.20.  Not per Tutorial D spec.
   Infix SUMMARIZE added as of 1.0.20.  Not per Tutorial D spec.
   rel_monadic() and rel_dyadic() combined and changed to rel_op() to
   give monadic and dyadic ops equal precedence.
*/
void rel_op() :
{}
{
    rel_project() (
            <RENAME> "{" renaming_commalist() "}"                                       //#AlgRename(2)
        |   <EXTEND> [ ":" ] "{" extend_add_commalist() "}"                             //#AlgExtend(2)
        |   <RANK> [ <BY> ] "(" order_item_commalist() <AS> identifier() ")"            //#AlgRank(3)
        |   <SUMMARIZE> per_or_by() [ ":" ] "{" summarize_add_commalist() "}"           //#AlgSummarize(3)
        |   <UPDATE> [ ":" ] update_assignment()                                        //#AlgUpdate(2)
        |   <WRAP> wrapping()                                                           //#AlgWrap(2)
        |   <UNWRAP> identifier()                                                       //#AlgUnwrap(2) 
        |   <GROUP> grouping()
        |   <UNGROUP> identifier()                                                      //#AlgUngroup(2)
        |   <DIVIDEBY> expression() <PER> "(" expression() divide_per_optional() ")"    //#AlgDivide(4)
        |   <UNION> rel_project()                                                       //#AlgUnion(2) 
        |   <XUNION> rel_project()                                                      //#AlgXunion(2)
        |   <D_UNION> rel_project()                                                     //#AlgDUnion(2) 
        |   <INTERSECT> rel_project()                                                   //#AlgIntersect(2)
        |   <MINUS> rel_project()                                                       //#AlgMinus(2)
        |   <I_MINUS> rel_project()                                                     //#AlgIMinus(2)
        |   <JOIN> rel_project()                                                        //#AlgJoin(2)
        |   <LEFT> <JOIN> rel_project()                                                 //#AlgLeftJoin(2)
        |   <RIGHT> <JOIN> rel_project()                                                //#AlgRightJoin(2)
        |   <FULL> <JOIN> rel_project()                                                 //#AlgFullJoin(2)
        |   <TIMES> rel_project()                                                       //#AlgTimes(2)
        |   <COMPOSE> rel_project()                                                     //#AlgCompose(2)
        |   ( <SEMIJOIN> | <MATCHING> ) rel_project()                                   //#AlgSemijoin(2)
        |   ( <SEMIMINUS> | <NOT> <MATCHING> ) rel_project()                            //#AlgSemiminus(2) 
    )*
}

/* Not explicitly defined in TTM3 */
void order_item_commalist() /*#OrderItemCommalist*/ :
{}
{
    [ order_item() ( "," order_item() )* ]
}

void order_item() :
{}
{
      <ASC>    identifier()  //#OrderItemAsc 
    | <DESC>   identifier()  //#OrderItemDesc
}

void divide_per_optional() /*#AlgDividePerOptional*/ :
{}
{
    [ "," expression() ]
}

void grouping() :
{}
{
    "{" attribute_name_list() "}" <AS> identifier() //#Group(3)
}

void wrapping() /*#WrappingItem*/ :
{}
{
    "{" attribute_name_list() "}" <AS> identifier()
}

void renaming_commalist() /*#RenamingList*/ :
{}
{
    [ renaming() ( "," renaming() )* ]
}

void renaming() :
{}
{
        renaming_simple()
    |   renaming_prefix()
    |   renaming_suffix()
}

void renaming_simple() /*#RenamingSimple*/ :
{}
{
    identifier() <AS> identifier()
}

void renaming_prefix() /*#RenamingPrefix*/ :
{}
{
    <PREFIX> string_literal() <AS> string_literal()
}

void renaming_suffix() /*#RenamingSuffix*/ :
{}
{
    <SUFFIX> string_literal() <AS> string_literal() 
}

void attribute_name_list() /*#AttributeNameList*/ :
{}
{
    optional_all_but() attribute_name_commalist()
}

void optional_all_but() /*#AllBut*/ :
{}
{
    [ <ALL> <BUT> /*#AllBut*/ ]
}

void attribute_name_commalist() :
{}
{
        attribute_name_commalist_attributes_of()
    |   attribute_name_commalist_list() 
}

void attribute_name_commalist_attributes_of() /*#AttributeNameCommalistListAttributesOf*/ :
{}
{
    <ATTRIBUTES_OF> "(" expression() ")"
}

void attribute_name_commalist_list() /*#AttributeNameCommalistList*/ :
{}
{
    [ identifier() ( "," identifier() )* ]
}

void rel_project() :
{}
{
    add_expression() [ "{" attribute_name_list() "}" /*#AlgProject(2)*/ ]
}

void add_expression() : 
{} 
{
    mul_expression() (
            <PLUS>      mul_expression() //#Add(2)
        |   <SUBT>      mul_expression() //#Subtract(2)
        |   <BARBAR>    mul_expression() //#Concatenate(2)
    )*
}

void mul_expression() : 
{} 
{ 
    unary_expression() ( 
            (<STAR> | <MULT_U>)         unary_expression() //#Times(2)
        |   (<DIVD_A> | <DIVD_U>)       unary_expression() //#Divide(2)
        |   <MODL>                      unary_expression() //#Mod(2)
    )*
}

void unary_expression() :
{}
{
        <NOT>           unary_expression() //#UnaryNot(1)
    |   <PLUS>          unary_expression() //#UnaryPlus(1)
    |   <SUBT>          unary_expression() //#UnaryMinus(1)
    |                   primary_expression()
}

void primary_expression() : 
{}
{
        literal()
    |   LOOKAHEAD(2) aggregate_operator()
    |   exactly()
    |   nadic_or()
    |   nadic_equiv()
    |   nadic_xor()
    |   nadic_and()
    |   nadic_union()
    |   nadic_xunion()
    |   nadic_disjoint_union()
    |   nadic_intersect()
    |   nadic_join()
    |   nadic_times()
    |   nadic_compose()
    |   nadic_count()
    |   nadic_sum()
    |   nadic_avg()
    |   nadic_max()
    |   nadic_min()
    |   extend()
    |   rank()
    |   summarize()
    |   substitute()
    |   case_expression()
    |   if_expression()
    |   search()
    |   type_of()
    |   image_in()
    |   LOOKAHEAD(2) fn_invoke() 
    |   dereference() 
    |   "(" expression() ")"
}

void search() /*#Search*/ :
{}
{
    <SEARCH> "(" expression() "," expression() ")"
}

void type_of() /*#TypeOf*/ :
{}
{
    <TYPE_OF> "(" expression() ")"
}

void image_in() :
{}
{
        (<BANGBANG_A> | <BANGBANG_U>) (image_in_bracketed() | image_in_identifier())
    |   <IMAGE_IN> image_in_bracketed()
}

void image_in_bracketed() /*#ImageIn*/ :
{}
{
    "(" expression() [ "," expression() ] ")"
}

void image_in_identifier() /*#ImageBangBang*/ :
{}
{
    identifier()
}

void case_expression() /*#CaseExpression*/ :
{}
{
    <CASE> 
    when_def_list_expr() 
    <ELSE> expression() 
    <END> [ <CASE> ]
}

void when_def_list_expr() /*#CaseWhenListExpression*/ :
{}
{
    when_def_expr() ( when_def_expr() )*
}

void when_def_expr() /*#CaseWhenExpression*/ :
{}
{
    <WHEN> expression() <THEN> expression()
}

void if_expression() /*#IfExpression*/ :
{}
{
    <IF> expression() <THEN> expression() 
    <ELSE> expression()
    <END> [ <IF> ]
}

/* Update expression, *not* assignment.
Contents of expression() does not change! */
void substitute() /*#Substitute*/ :
{}
{
    <UPDATE> expression() ":" update_assignment()
}

void nadic_optional_heading() :
{}
{
         LOOKAHEAD(heading() "{" heading_exp_commalist() "}") heading() /*#NadicHeading*/ "{" heading_exp_commalist() "}"
       | "{" heading_exp_commalist() "}" 
}

void nadic_union() /*#NadicUnion*/ :
{}
{
    <UNION> nadic_optional_heading()
}

void nadic_xunion() /*#NadicXunion*/ :
{}
{
    <XUNION> nadic_optional_heading()
}

void nadic_disjoint_union() /*#NadicDUnion*/ :
{}
{
    <D_UNION> nadic_optional_heading()
}

void nadic_intersect() /*#NadicIntersect*/ :
{}
{
    <INTERSECT> nadic_optional_heading()
}

void nadic_join() /*#NadicJoin*/ :
{}
{
    <JOIN> "{" heading_exp_commalist() "}"
}

void nadic_times() /*#NadicTimes*/ :
{}
{
    <TIMES> "{" heading_exp_commalist() "}"
}

void nadic_compose() /*#NadicCompose*/ :
{}
{
    <COMPOSE> "{" heading_exp_commalist() "}"
}

void nadic_or() /*#NadicOr*/ :
{}
{
    <OR> "{" bool_exp_commalist() "}"
}

void nadic_equiv() /*#NadicEquiv*/ :
{}
{
    <EQUIV> "{" bool_exp_commalist() "}" 
}

void nadic_xor() /*#NadicXor*/ :
{}
{
    <XOR> "{" bool_exp_commalist() "}"
}

void nadic_and() /*#NadicAnd*/ :
{}
{
    <AND> "{" bool_exp_commalist() "}"
}

void nadic_count() /*#NadicCount*/ :
{}
{
    <COUNT> "{" exp_commalist() "}"
}

void nadic_sum() /*#NadicSum*/ :
{}
{
    <SUM> "{" exp_commalist() "}"
}

void nadic_avg() /*#NadicAvg*/ :
{}
{
    <AVG> "{" exp_commalist() "}"
}

void nadic_max() /*#NadicMax*/ :
{}
{
    <MAX> "{" exp_commalist() "}"
}

void nadic_min() /*#NadicMin*/ :
{}
{
    <MIN> "{" exp_commalist() "}"
}

void exactly() /*#Exactly*/ :
{}
{
    <EXACTLY> "(" expression() [ "," expression() ( "," expression() )* ] ")"
}

void exp_commalist() /*#ExpressionCommalist*/ :
{}
{
    [ expression() ( "," expression() )* ]
}

void bool_exp_commalist() /*#BooleanExpressionCommalist*/ :
{}
{
    [ expression() ( "," expression() )* ]
}

void heading_exp_commalist() /*#HeadingExpCommalist*/ :
{}
{
    [ expression() ( "," expression() )* ] 
}

void extend() /*#Extend*/ :
{}
{
    <EXTEND> expression() ":" "{" extend_add_commalist() "}"
}

void rank() /*#Rank*/ :
{}
{
  <RANK> expression() <BY> "(" order_item_commalist() <AS> identifier() ")"
}

void extend_add_commalist() /*#ExtendList*/ :
{}
{
    [ extend_add() ( "," extend_add() )* ]
}

void extend_add() /*#ExtendItem*/ :
{}
{
    identifier() ":=" expression()
}

void summarize() /*#Summarize*/ :
{}
{
    <SUMMARIZE> expression() per_or_by() ":" "{" summarize_add_commalist() "}"
}

void per_or_by() /*#SummarizePerOrBy*/ :
{}
{
    [
            <PER> "(" expression() ")" //#SummarizePer(1)
        |   <BY> "{" attribute_name_list() "}" //#SummarizeBy(1)
    ]
}

void summarize_add_commalist() /*#SummarizeItems*/ :
{}
{
    summarize_add() ( "," summarize_add() )*
}

void summarize_add() /*#SummarizeItem*/ :
{}
{
    identifier() ":=" summary()
}

void summary() :
{}
{
        <COUNT> "(" ")"                                     //#SummarizeCount
    |   <COUNTD> "(" expression() ")"                       //#SummarizeCountDistinct(1)
    |   <SUM> "(" expression() ")"                          //#SummarizeSum(1)
    |   <SUMD> "(" expression() ")"                         //#SummarizeSumDistinct(1)
    |   <AVG> "(" expression() ")"                          //#SummarizeAvg(1)
    |   <AVGD> "(" expression() ")"                         //#SummarizeAvgDistinct(1)
    |   <MAX> "(" expression() ")"                          //#SummarizeMax(1)
    |   <MIN> "(" expression() ")"                          //#SummarizeMin(1)
    |   <AND> "(" expression() ")"                          //#SummarizeAnd(1)
    |   <OR> "(" expression() ")"                           //#SummarizeOr(1)
    |   <EQUIV> "(" expression() ")"                        //#SummarizeEquiv(1)
    |   <XOR> "(" expression() ")"                          //#SummarizeXor(1)
    |   <EXACTLY> "(" expression() "," expression() ")"     //#SummarizeExactly(2)
    |   <EXACTLYD> "(" expression() "," expression() ")"    //#SummarizeExactlyDistinct(2)
    |   <UNION> "(" expression() ")"                        //#SummarizeUnion(1)
    |   <XUNION> "(" expression() ")"                       //#SummarizeXunion(1)
    |   <D_UNION> "(" expression() ")"                      //#SummarizeDUnion(1)
    |   <INTERSECT> "(" expression() ")"                    //#SummarizeIntersect(1)
    |   summarize_aggregate()
    |   summarize_aggregated()
    |   summarize_userdefined()
}

/* Rel extension. */
void summarize_aggregate() /*#SummarizeAggregate*/ :
{}
{
    <AGGREGATE> "(" expression() [ "," expression() ] ")" ";"   
        op_body()           // VALUE1 and VALUE2 introduced
    <END> [ <AGGREGATE> ]
}

/* Rel extension. */
void summarize_aggregated() /*#SummarizeAggregateDistinct*/ :
{}
{
    <AGGREGATED> "(" expression() [ "," expression() ] ")" ";"  
        op_body()           // VALUE1 and VALUE2 introduced
    <END> [ <AGGREGATED> ]
}

/* Rel extension. */
void summarize_userdefined() /*#SummarizeUserdefined*/ :
{}
{
    identifier() "(" SummarizeItemDistinct() expression() [ "," expression() ] ")" 
}

/* Rel extension. */
void SummarizeItemDistinct() /*#SummarizeUserdefinedDistinct*/ :
{}
{
    [ SummarizeItemDistinctTrue() ]
}

/* Rel extension. */
void SummarizeItemDistinctTrue() /*#SummarizeUserdefinedDistinctTrue*/ :
{}
{
    <DISTINCT>
}

void fn_invoke() /*#FnInvoke*/ :
{}
{
    identifier() "(" arglist() ")"
}

void arglist() /*#ArgList*/ :
{}
{
    [ expression() ( "," expression() )* ]
}

void aggregate_operator() :
{}
{
        <COUNT> "(" expression() ")"                                                //#AggCount(1)
    |   <SUM> "(" expression() "," expression() ")"                                 //#AggSum(2)
    |   <AVG> "(" expression() "," expression() ")"                                 //#AggAvg(2)
    |   <MAX> "(" expression() "," expression() ")"                                 //#AggMax(2)
    |   <MIN> "(" expression() "," expression() ")"                                 //#AggMin(2)                
    |   <AND> "(" expression() "," expression() ")"                                 //#AggAnd(2)
    |   <OR> "(" expression() "," expression() ")"                                  //#AggOr(2)
    |   <EQUIV> "(" expression() "," expression() ")"                               //#AggEquiv(2)
    |   <XOR> "(" expression() "," expression() ")"                                 //#AggXor(2)
    |   <UNION> "(" expression() "," expression() ")"                               //#AggUnion(2)
    |   <XUNION> "(" expression() "," expression() ")"                              //#AggXunion(2)
    |   <D_UNION> "(" expression() "," expression() ")"                             //#AggDUnion(2)
    |   <INTERSECT> "(" expression() "," expression() ")"                           //#AggIntersect(2)
    |   agg_aggregate()
}

void agg_aggregate() :
{}
{
    <AGGREGATE>
    (
        agg_aggregate_inline()
    |   agg_aggregate_userdefined()
    ) 
}

/* Rel extension. */
void agg_aggregate_inline() /*#AggAggregate*/ :
{}
{
    "(" expression() "," expression() [ "," expression() ] ")" ";"  
        op_body()           // VALUE1 and VALUE2 introduced
    <END> [ <AGGREGATE> ]
}

/* Rel extension. */
void agg_aggregate_userdefined() /*#AggAggregateUserdefined()*/ :
{}
{
    identifier() "(" expression() "," expression() [ "," expression() ] ")"
}

void literal() :
{}
{
        lambda()
    |   tuple()
    |   relation()
    |   integer()
    |   character()                             
    |   rational()
    |   bool()
}

void tuple() /*#Tuple*/ :
{}
{
    <TUPLE> "{" ( tuple_component_wildcard() | [ tuple_component_commalist() ] ) "}"
}

void tuple_component_wildcard() /*#TupleComponentWildcard*/ :
{}
{
    <STAR>
}

void tuple_component_commalist() :
{}
{
    tuple_component() ( "," tuple_component() )*
}

void tuple_component() /*#TupleComponent*/ :
{}
{
    identifier() expression()
}

void relation() :
{}
{
        <RELATION> relation_heading() "{" tuple_exp_commalist() "}"     //#Relation(2)
    |   <TABLE_DUM>                                                     //#RelationDum
    |   <TABLE_DEE>                                                     //#RelationDee
}

void relation_heading() /*#RelationHeading*/ :
{}
{
    [ LOOKAHEAD(heading_type()) heading_type() ]
}

void heading() /*#Heading*/ :
{}
{
    "{" [ attribute_spec_commalist() ] "}"
}

void tuple_exp_commalist() /*#TupleExpressionCommalist*/ :
{}
{
    [ expression() ( "," expression() )* ]
}

void attribute_spec_commalist() :
{}
{
    attribute_spec() ( "," attribute_spec() )*
}

void attribute_spec() /*#AttributeSpec*/ :
{}
{
    identifier() type_ref()
}

void identifier() /*#Identifier*/ :
{Token t;}
{
    t = <IDENTIFIER> {jjtThis.tokenValue = t.image;}
}

void dereference() /*#Dereference*/ :
{Token t;}
{
    t = <IDENTIFIER> {jjtThis.tokenValue = t.image;}
}

void character() /*#Character*/ :
{Token t;}
{
    t = <STRING_LITERAL> {jjtThis.tokenValue = t.image;}
}

void string_literal() /*#StringLiteral*/ :
{Token t;}
{
    t = <STRING_LITERAL> {jjtThis.tokenValue = t.image;}
}

void integer() /*#Integer*/ : 
{Token t;} 
{ 
    t = <INTEGER_LITERAL> {jjtThis.tokenValue = t.image;}
}

void rational() /*#Rational*/ : 
{Token t;} 
{
        t = <FLOATING_POINT_LITERAL> {jjtThis.tokenValue = t.image;}
    |   t = <INFINITY> {jjtThis.tokenValue = t.image;}
    |   t = <NAN> {jjtThis.tokenValue = t.image;}
}

void bool() : 
{}
{
        <TRUE> /*#True*/
    |   <FALSE> /*#False*/
}
DaveVoorhis commented 1 year ago

I've modified the Rel buildProduct.sh script (in the _Deployment directory) to automatically prepare the grammar and emit it as railroad diagrams. Example output is at https://reldb.org/c/index.php/grammar/

mingodad commented 1 year ago

Nice work ! I hope it'll help new users onboard on this project.