我正在尝试为 DB2 DDL 语句 (CREATE TABLE) 构建 ANTLR 3 语法,我发现决策可以使用多种替代方法匹配诸如“DATA”之类的输入:1、2。我正在关注 DB2 DDL 文档文档。
我已经将语法图准确地映射到语法。但问题是有一些可选子句和路径可以到达同一点,因此有多种选择。我使用了回溯选项,但我想要其他一些解决方案。任何人都可以在这方面帮助我。
请看我的语法:
unit:
create_table_statement
;
create_table_statement:
create_table_statement_rest
;
create_table_statement_rest:
CREATE TABLE ID create_table_opts
organize_by_items?
DATA CAPTURE (NONE|CHANGES) in_tbspc_cyc
tablespace_opts? distribution_clause?
partitioning_clause? compress_ny_val_compression
with_restrict_on_drop? not_logged_init?
ccsid_ascii_unicode? (SECURITY POLICY name)?
(OPTIONS LPAREN ADD name name (COMMA name name)* RPAREN)?
;
with_restrict_on_drop:
WITH RESTRICT ON DROP
;
not_logged_init:
NOT LOGGED INITIALLY
;
ccsid_ascii_unicode:
CCSID (ASCII|UNICODE)
;
create_table_opts:
element_list
|OF name typed_table_opts?
|materialized_query_definition
|staging_table_definition
|LIKE name copy_opts?
;
organize_by_items:
ORGANIZE BY (dimensions_item|key_sequence_items)
;
dimensions_item:
DIMENSIONS? LPAREN ID (COMMA ID)* RPAREN
;
key_sequence_items:
KEY SEQUENCE sequence_key_spec
;
sequence_key_spec:
LPAREN seq_key_spec_one (COMMA seq_key_spec_one) RPAREN (ALLOW|DISALLOW) OVERFLOW (PCTFREE DIGIT)?
;
seq_key_spec_one:
ID (STARTING FROM? CONSTANT)? ENDING AT? DIGIT
;
in_tbspc_cyc:
IN (name (COMMA name)*) NO? CYCLE?
;
tablespace_opts:
//tablespace_opt_one?
(INDEX IN name)? (LOG IN name (COMMA name)*)?
;
distribution_clause:
DISTRIBUTE BY distribute_by_opts
;
distribute_by_opts:
distribution_item_one
|distribution_item_two
;
distribute_by:
DISTRIBUTE BY
;
distribution_item_one:
HASH LPAREN ID (COMMA ID)* RPAREN
;
distribution_item_two:
REPLICATION
;
tablespace_opt_one:
INDEX IN name LOG IN name
;
element_list:
LPAREN
element_list_items (COMMA element_list_items)*
RPAREN
;
materialized_query_definition:
(ID (COMMA ID)*)? AS LPAREN fullselect RPAREN materialized_query_table_opts
;
staging_table_definition:
(LPAREN name (COMMA name)* RPAREN) FOR name PROPAGATE IMMEDIATE
;
fullselect:
;
materialized_query_table_opts:
WITH NO DATA copy_opts? | refreshable_table_opts
;
element_list_items:
column_definition|referential_constraint|check_constraint
;
column_definition:
name data_type? column_opts?
;
copy_opts:
((INCLUDING|EXCLUDING) COLUMN? DEFAULTS)? (EXCLUDING|INCLUDING) IDENTITY (COLUMN ATTRIBUTES)?
;
refreshable_table_opts:
DATA INITIALLY DEFERRED REFRESH (DEFERRED|IMMEDIATE) (ENABLE|DISABLE) QUERY OPTIMIZATION (MAINTAINED BY (SYSTEM|USER|FEDERATED_TOOL))?
;
data_type:
SMALLINT
|INTEGER|INT
|BIGINT
|FLOAT (LPAREN DIGIT RPAREN)?
|REAL
|DOUBLE PRECISION?
|(DECIMAL|DEC|NUMERIC|NUM) (LPAREN DIGIT (COMMA INTEGER)? RPAREN)?
|(dt_char|dt_vchar|LONG VARCHAR) (FOR BIT DATA)?
|((BLOB|BINARY LARGE OBJECT)|(CLOB|(CHARACTER|CHAR) LARGE OBJECT|DBCLOB) (LPAREN DIGIT (K|M|G) RPAREN)?)
|GRAPHIC (LPAREN DIGIT RPAREN)
|VARGRAPHIC (LPAREN DIGIT RPAREN)
|LONG VARGRAPHIC
|DATE
|TIME
|TIMESTAMP
|XML
//|name
//added name instead of the two below but it would be replaced
//|distinct_type_name
//|structured_type_name
|REF name
|(LPAREN SYSPROC DOT RPAREN)? DB2SECURITYLABEL
;
dt_char : (CHARACTER|CHAR)(LPAREN DIGIT RPAREN)?
;
dt_vchar :
(VARCHAR|((CHAR|CHARACTER) VARYING))LPAREN DIGIT RPAREN
;
distinct_type_name
:
name
;
structured_type_name
:
name
;
column_opts:
column_options_items+
;
column_options_items:
NOT NULL
|lob_opts
|SCOPE name
|((CONSTRAINT name)? ((PRIMARY KEY|UNIQUE)| references_clause|(check_condition constraint_attributes)))
|generated_column_spec
|(INLINE LENGTH DIGIT)
|(COMPRESS SYSTEM DEFAULT)
|(COLUMN SECURED WITH ID)
;
lob_opts:
NOT? LOGGED NOT? COMPACT
;
generated_column_spec:
default_clause|generated_by_identity|generated_by_exp
;
default_clause:
WITH? DEFAULT default_values?
;
default_values:
default_values_items
|cast_function LPAREN default_values_items RPAREN
|NULL
;
default_values_items
:
constant
|datetime_special_register
|user_special_register
|CURRENT SCHEMA
;
datetime_special_register:
CURRENT DATE
|CURRENT TIME
|CURRENT TIMESTAMP
;
user_special_register:
CURRENT USER
|SESSION_USER
|SYSTEM_USER
;
cast_function:
//needs to be figured out
;
generated_by_identity:
GENERATED (ALWAYS|(BY DEFAULT)) identity_opts?
;
identity_opts:
AS IDENTITY LPAREN identity_options_items (identity_options_items)* RPAREN
;
identity_options_items:
START WITH DIGIT
|INCREMENT BY DIGIT
|NO MINVALUE
|MINVALUE DIGIT
|NO MAXVALUE
|MAXVALUE DIGIT
|NO CYCLE
|CYCLE
| (NO CACHE | CACHE DIGIT)//cache 20 needs to be seen
|NO ORDER
|ORDER
;
generated_by_exp:
GENERATED ALWAYS? AS generation_expression
;
generation_expression:
//needs to be figured out
;
unique_constraint:
(CONSTRAINT name)? (UNIQUE|PRIMARY KEY) LPAREN name (COMMA name)* RPAREN
;
referential_constraint:
(CONSTRAINT ID)? FOREIGN KEY LPAREN ID (COMMA ID)* RPAREN references_clause
;
references_clause:
REFERENCES name (LPAREN ID (COMMA ID)* RPAREN)? rule_clause constraint_attributes
;
rule_clause:
ON DELETE (NO ACTION | RESTRICT|CASCADE|SET NULL) ON UPDATE (NO ACTION|RESTRICT)
;
check_constraint:
(CONSTRAINT name) CHECK check_condition constraint_attributes
;
check_condition:
search_condition|functional_dependency
;
constraint_attributes:
NOT? ENFORCED (ENABLE|DISABLE) QUERY OPTIMIZATION
;
search_condition:
//needs to be done
;
functional_dependency:
(ID | (LPAREN ID (COMMA ID)* RPAREN)) DETERMINED BY (ID | (LPAREN ID (COMMA ID)* RPAREN))
;
typed_table_opts:
(HIERARCHY name|under_clause)? typed_element_list?
;
typed_table_options_item2:
under_clause
;
under_clause:
UNDER name INHERIT SELECT PRIVILEGES
;
typed_element_list:
LPAREN typed_element_list_items (COMMA typed_element_list_items)* RPAREN
;
typed_element_list_items:
oid_column_definition | with_opts | unique_constraint | check_constraint
;
oid_column_definition:
REF IS name USER GENERATED
;
with_opts:
name WITH OPTIONS column_opts
;
partitioning_clause:
part_by_range range_partition_spec
;
part_by_range:
PARTITION BY RANGE?
;
compress_ny_val_compression:
COMPRESS (NO|YES) (VALUE COMPRESSION)?
;
range_partition_spec:
LPAREN partition_expression (COMMA partition_expression)* RPAREN LPAREN partition_element (COMMA partition_element)* RPAREN
;
partition_element:
partition_boundry_element
|start_with_boundry_spec
;
partition_boundry_element:
(PARTITION name)? boundary_spec (IN name)?
;
start_with_boundry_spec:
boundary_spec EVERY (duration_with_paren|duration_without_paren)
;
duration_with_paren:
LPAREN constant duration_label RPAREN
;
duration_without_paren:
constant duration_label
;
partition_expression:
NULLS (LAST|FIRST)
;
boundary_spec:
boundary_spec_path_one|boundary_spec_path_two
;
boundary_spec_path_one:
starting_clause ending_clause
;
boundary_spec_path_two:
ending_clause
;
starting_clause:
STARTING FROM? (starting_ending_with_repeat|starting_ending_without_repeat) (INCLUSIVE|EXCLUSIVE)
;
ending_clause:
ENDING AT? (starting_ending_with_repeat|starting_ending_without_repeat) (INCLUSIVE|EXCLUSIVE)
;
starting_ending_with_repeat:
LPAREN starting_ending_clause_values (COMMA starting_ending_clause_values)* RPAREN
;
starting_ending_without_repeat:
starting_ending_clause_values
;
duration_label:
YEAR|YEARS|MONTH|MONTHS|DAY|DAYS|HOUR|HOURS|MINUTE|MINUTES|SECOND|SECONDS|MICROSECOND|MICROSECONDS
;
starting_ending_clause_values:
constant|MINVALUE|MAXVALUE
;
constant:
DIGIT
;
name : ID;
///////////////////////////////////////////////END PARSER RULES///////////////////////////////////////////////////
///////////////////////////////////////////////LEXER RULES///////////////////////////////////////////////////////
WS : ( '\t' | ' ' | '\r' | '\n' )+ { $channel = HIDDEN; } ;
COMMA
: ','
;
EQUAL:
'=';
STRING_LITERAL
: ('n'|'u')?'\''( ~('\'') | '\'\'' )* '\'' ;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
DIGIT : '0'..'9'+
;
在这方面的任何帮助将不胜感激。