SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] [ * | expression [ [ AS ] output_name ] [, ...] ] [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY grouping_element [, ...] ] [ HAVING condition [, ...] ] [ WINDOW window_name AS ( window_definition ) [, ...] ]
full_select_statement is basic_select_statement with the following possible additional clauses tacked onto the end:
[ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]
and that's still not right because ORDER BY et al can't be attached to a select_stmt that's the argument of a set operation, so really we'd need a couple of levels of nonterminals before we get down to the basic "SELECT expression FROM ..." part. Nor has the use of parentheses been mentioned yet.
Then we can define the set clauses in terms of basic_select_stmt and parentheses-surrounded full_select_stmt. The result of the set clause is itself a type of basic_select_statement which can be made full by adding one or more of the additional clauses, including ORDER BY.