cassandra/src/java/org/apache/cassandra/cli/Cli.g

626 lines
13 KiB
Plaintext

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ANTLR Grammar for the Cassandra Command Line Interface (CLI).
grammar Cli;
options {
output=AST;
ASTLabelType=CommonTree;
backtrack=true;
}
//
// Nodes in the AST
//
tokens {
//
// Top-level nodes. These typically correspond to
// various top-level CLI statements.
//
NODE_CONNECT;
NODE_DESCRIBE_TABLE;
NODE_DESCRIBE_CLUSTER;
NODE_USE_TABLE;
NODE_EXIT;
NODE_HELP;
NODE_NO_OP;
NODE_SHOW_CLUSTER_NAME;
NODE_SHOW_VERSION;
NODE_SHOW_KEYSPACES;
NODE_THRIFT_GET;
NODE_THRIFT_GET_WITH_CONDITIONS;
NODE_THRIFT_SET;
NODE_THRIFT_COUNT;
NODE_THRIFT_DEL;
NODE_THRIFT_INCR;
NODE_THRIFT_DECR;
NODE_ADD_COLUMN_FAMILY;
NODE_ADD_KEYSPACE;
NODE_DEL_KEYSPACE;
NODE_DEL_COLUMN_FAMILY;
NODE_UPDATE_KEYSPACE;
NODE_UPDATE_COLUMN_FAMILY;
NODE_LIST;
NODE_TRUNCATE;
NODE_ASSUME;
NODE_CONSISTENCY_LEVEL;
// Internal Nodes.
NODE_COLUMN_ACCESS;
NODE_ID_LIST;
NODE_NEW_CF_ACCESS;
NODE_NEW_KEYSPACE_ACCESS;
CONVERT_TO_TYPE;
FUNCTION_CALL;
CONDITION;
CONDITIONS;
ARRAY;
HASH;
PAIR;
NODE_LIMIT;
NODE_KEY_RANGE;
}
@parser::header {
package org.apache.cassandra.cli;
}
@lexer::header {
package org.apache.cassandra.cli;
}
@lexer::members
{
public void reportError(RecognitionException e)
{
StringBuilder errorMessage = new StringBuilder("Syntax error at position " + e.charPositionInLine + ": ");
if (e instanceof NoViableAltException)
{
int index = e.charPositionInLine;
String error = this.input.substring(index, index);
String statement = this.input.substring(0, this.input.size() - 1);
errorMessage.append("unexpected \"" + error + "\" for `" + statement + "`.");
}
else
{
errorMessage.append(this.getErrorMessage(e, this.getTokenNames()));
}
throw new RuntimeException(errorMessage.toString());
}
}
@parser::members
{
public void reportError(RecognitionException e)
{
String errorMessage;
if (e instanceof NoViableAltException)
{
errorMessage = "Command not found: `" + this.input + "`. Type 'help;' or '?' for help.";
}
else
{
errorMessage = "Syntax error at position " + e.charPositionInLine + ": " + this.getErrorMessage(e, this.getTokenNames());
}
throw new RuntimeException(errorMessage);
}
}
//
// Parser Section
//
// the root node
root: statement SEMICOLON? EOF -> statement;
statement
: connectStatement
| exitStatement
| countStatement
| describeTable
| describeCluster
| addKeyspace
| addColumnFamily
| updateKeyspace
| updateColumnFamily
| delColumnFamily
| delKeyspace
| useKeyspace
| delStatement
| getStatement
| helpStatement
| setStatement
| incrStatement
| showStatement
| listStatement
| truncateStatement
| assumeStatement
| consistencyLevelStatement
| -> ^(NODE_NO_OP)
;
connectStatement
: CONNECT host '/' port (username password)?
-> ^(NODE_CONNECT host port (username password)?)
| CONNECT ip_address '/' port (username password)?
-> ^(NODE_CONNECT ip_address port (username password)?)
;
helpStatement
: HELP HELP
-> ^(NODE_HELP NODE_HELP)
| HELP CONNECT
-> ^(NODE_HELP NODE_CONNECT)
| HELP USE
-> ^(NODE_HELP NODE_USE_TABLE)
| HELP DESCRIBE KEYSPACE
-> ^(NODE_HELP NODE_DESCRIBE_TABLE)
| HELP DESCRIBE 'CLUSTER'
-> ^(NODE_HELP NODE_DESCRIBE_CLUSTER)
| HELP EXIT
-> ^(NODE_HELP NODE_EXIT)
| HELP QUIT
-> ^(NODE_HELP NODE_EXIT)
| HELP SHOW 'CLUSTER NAME'
-> ^(NODE_HELP NODE_SHOW_CLUSTER_NAME)
| HELP SHOW KEYSPACES
-> ^(NODE_HELP NODE_SHOW_KEYSPACES)
| HELP SHOW API_VERSION
-> ^(NODE_HELP NODE_SHOW_VERSION)
| HELP CREATE KEYSPACE
-> ^(NODE_HELP NODE_ADD_KEYSPACE)
| HELP UPDATE KEYSPACE
-> ^(NODE_HELP NODE_UPDATE_KEYSPACE)
| HELP CREATE COLUMN FAMILY
-> ^(NODE_HELP NODE_ADD_COLUMN_FAMILY)
| HELP UPDATE COLUMN FAMILY
-> ^(NODE_HELP NODE_UPDATE_COLUMN_FAMILY)
| HELP DROP KEYSPACE
-> ^(NODE_HELP NODE_DEL_KEYSPACE)
| HELP DROP COLUMN FAMILY
-> ^(NODE_HELP NODE_DEL_COLUMN_FAMILY)
| HELP GET
-> ^(NODE_HELP NODE_THRIFT_GET)
| HELP SET
-> ^(NODE_HELP NODE_THRIFT_SET)
| HELP INCR
-> ^(NODE_HELP NODE_THRIFT_INCR)
| HELP DECR
-> ^(NODE_HELP NODE_THRIFT_DECR)
| HELP DEL
-> ^(NODE_HELP NODE_THRIFT_DEL)
| HELP COUNT
-> ^(NODE_HELP NODE_THRIFT_COUNT)
| HELP LIST
-> ^(NODE_HELP NODE_LIST)
| HELP TRUNCATE
-> ^(NODE_HELP NODE_TRUNCATE)
| HELP ASSUME
-> ^(NODE_HELP NODE_ASSUME)
| HELP CONSISTENCYLEVEL
-> ^(NODE_HELP NODE_CONSISTENCY_LEVEL)
| HELP
-> ^(NODE_HELP)
| '?'
-> ^(NODE_HELP)
;
exitStatement
: QUIT -> ^(NODE_EXIT)
| EXIT -> ^(NODE_EXIT)
;
getStatement
: GET columnFamilyExpr ('AS' typeIdentifier)? ('LIMIT' limit=IntegerPositiveLiteral)?
-> ^(NODE_THRIFT_GET columnFamilyExpr ( ^(CONVERT_TO_TYPE typeIdentifier) )? ^(NODE_LIMIT $limit)?)
| GET columnFamily 'WHERE' getCondition ('AND' getCondition)* ('LIMIT' limit=IntegerPositiveLiteral)?
-> ^(NODE_THRIFT_GET_WITH_CONDITIONS columnFamily ^(CONDITIONS getCondition+) ^(NODE_LIMIT $limit)?)
;
getCondition
: columnOrSuperColumn operator value
-> ^(CONDITION operator columnOrSuperColumn value)
;
operator
: '=' | '>' | '<' | '>=' | '<='
;
typeIdentifier
: Identifier | StringLiteral | IntegerPositiveLiteral
;
setStatement
: SET columnFamilyExpr '=' objectValue=value (WITH TTL '=' ttlValue=IntegerPositiveLiteral)?
-> ^(NODE_THRIFT_SET columnFamilyExpr $objectValue ( $ttlValue )?)
;
incrStatement
: INCR columnFamilyExpr (BY byValue=incrementValue)?
-> ^(NODE_THRIFT_INCR columnFamilyExpr ( $byValue )?)
| DECR columnFamilyExpr (BY byValue=incrementValue)?
-> ^(NODE_THRIFT_DECR columnFamilyExpr ( $byValue )?)
;
countStatement
: COUNT columnFamilyExpr
-> ^(NODE_THRIFT_COUNT columnFamilyExpr)
;
delStatement
: DEL columnFamilyExpr
-> ^(NODE_THRIFT_DEL columnFamilyExpr)
;
showStatement
: showClusterName
| showVersion
| showKeyspaces
;
listStatement
: LIST columnFamily keyRangeExpr? ('LIMIT' limit=IntegerPositiveLiteral)?
-> ^(NODE_LIST columnFamily keyRangeExpr? ^(NODE_LIMIT $limit)?)
;
truncateStatement
: TRUNCATE columnFamily
-> ^(NODE_TRUNCATE columnFamily)
;
assumeStatement
: ASSUME columnFamily assumptionElement=Identifier 'AS' defaultType=Identifier
-> ^(NODE_ASSUME columnFamily $assumptionElement $defaultType)
;
consistencyLevelStatement
: CONSISTENCYLEVEL 'AS' defaultType=Identifier
-> ^(NODE_CONSISTENCY_LEVEL $defaultType)
;
showClusterName
: SHOW 'CLUSTER NAME'
-> ^(NODE_SHOW_CLUSTER_NAME)
;
addKeyspace
: CREATE KEYSPACE keyValuePairExpr
-> ^(NODE_ADD_KEYSPACE keyValuePairExpr)
;
addColumnFamily
: CREATE COLUMN FAMILY keyValuePairExpr
-> ^(NODE_ADD_COLUMN_FAMILY keyValuePairExpr)
;
updateKeyspace
: UPDATE KEYSPACE keyValuePairExpr
-> ^(NODE_UPDATE_KEYSPACE keyValuePairExpr)
;
updateColumnFamily
: UPDATE COLUMN FAMILY keyValuePairExpr
-> ^(NODE_UPDATE_COLUMN_FAMILY keyValuePairExpr)
;
delKeyspace
: DROP KEYSPACE keyspace
-> ^(NODE_DEL_KEYSPACE keyspace)
;
delColumnFamily
: DROP COLUMN FAMILY columnFamily
-> ^(NODE_DEL_COLUMN_FAMILY columnFamily)
;
showVersion
: SHOW API_VERSION
-> ^(NODE_SHOW_VERSION)
;
showKeyspaces
: SHOW KEYSPACES
-> ^(NODE_SHOW_KEYSPACES)
;
describeTable
: DESCRIBE KEYSPACE (keyspace)?
-> ^(NODE_DESCRIBE_TABLE (keyspace)?)
;
describeCluster
: DESCRIBE 'CLUSTER'
-> ^(NODE_DESCRIBE_CLUSTER)
;
useKeyspace
: USE keyspace ( username )? ( password )?
-> ^(NODE_USE_TABLE keyspace ( username )? ( password )?)
;
keyValuePairExpr
: objectName ( (AND | WITH) keyValuePair )*
-> ^(NODE_NEW_KEYSPACE_ACCESS objectName ( keyValuePair )* )
;
keyValuePair
: attr_name '=' attrValue
-> attr_name attrValue
;
attrValue
: arrayConstruct
| attrValueString
| attrValueInt
| attrValueDouble
;
arrayConstruct
: '[' (hashConstruct ','?)+ ']'
-> ^(ARRAY (hashConstruct)+)
;
hashConstruct
: '{' hashElementPair (',' hashElementPair)* '}'
-> ^(HASH (hashElementPair)+)
;
hashElementPair
: rowKey ':' value
-> ^(PAIR rowKey value)
;
columnFamilyExpr
: columnFamily '[' rowKey ']'
( '[' column=columnOrSuperColumn ']'
('[' super_column=columnOrSuperColumn ']')?
)?
-> ^(NODE_COLUMN_ACCESS columnFamily rowKey ($column ($super_column)? )?)
;
keyRangeExpr
: '[' ( startKey? ':' endKey? )? ']'
-> ^(NODE_KEY_RANGE startKey? endKey?)
;
columnName
: Identifier
;
attr_name
: Identifier
;
attrValueString
: (Identifier | StringLiteral)
;
attrValueInt
: IntegerPositiveLiteral
| IntegerNegativeLiteral
;
attrValueDouble
: DoubleLiteral
;
objectName
: Identifier
;
keyspace
: Identifier
;
replica_placement_strategy
: StringLiteral
;
keyspaceNewName
: Identifier
;
comparator
: StringLiteral
;
command : Identifier
;
newColumnFamily
: Identifier
;
username: Identifier
;
password: StringLiteral
;
columnFamily
: Identifier
;
rowKey
: (Identifier | StringLiteral | IntegerPositiveLiteral | IntegerNegativeLiteral | functionCall)
;
value
: (Identifier | IntegerPositiveLiteral | IntegerNegativeLiteral | StringLiteral | functionCall)
;
functionCall
: functionName=Identifier '(' functionArgument? ')'
-> ^(FUNCTION_CALL $functionName functionArgument?)
;
functionArgument
: Identifier | StringLiteral | IntegerPositiveLiteral | IntegerNegativeLiteral
;
startKey
: (Identifier | StringLiteral)
;
endKey
: (Identifier | StringLiteral)
;
columnOrSuperColumn
: (Identifier | IntegerPositiveLiteral | IntegerNegativeLiteral | StringLiteral | functionCall)
;
host
: host_name
-> ^(NODE_ID_LIST host_name)
;
host_name
: Identifier ('.' Identifier)*
;
ip_address
: IP_ADDRESS
-> ^(NODE_ID_LIST IP_ADDRESS)
;
port
: IntegerPositiveLiteral
;
incrementValue
: IntegerPositiveLiteral
| IntegerNegativeLiteral
;
//
// Lexer Section
//
//
// Keywords (in alphabetical order for convenience)
//
// CLI is case-insensitive with respect to these keywords.
// However, they MUST be listed in upper case here.
//
CONFIG: 'CONFIG';
CONNECT: 'CONNECT';
COUNT: 'COUNT';
DEL: 'DEL';
DESCRIBE: 'DESCRIBE';
USE: 'USE';
GET: 'GET';
HELP: 'HELP';
EXIT: 'EXIT';
FILE: 'FILE';
QUIT: 'QUIT';
SET: 'SET';
INCR: 'INCR';
DECR: 'DECR';
SHOW: 'SHOW';
KEYSPACE: 'KEYSPACE';
KEYSPACES: 'KEYSPACES';
API_VERSION: 'API VERSION';
CREATE: 'CREATE';
DROP: 'DROP';
COLUMN: 'COLUMN';
FAMILY: 'FAMILY';
WITH: 'WITH';
BY: 'BY';
AND: 'AND';
UPDATE: 'UPDATE';
LIST: 'LIST';
LIMIT: 'LIMIT';
TRUNCATE: 'TRUNCATE';
ASSUME: 'ASSUME';
TTL: 'TTL';
CONSISTENCYLEVEL: 'CONSISTENCYLEVEL';
IP_ADDRESS
: IntegerPositiveLiteral '.' IntegerPositiveLiteral '.' IntegerPositiveLiteral '.' IntegerPositiveLiteral
;
// private syntactic rules
fragment
Letter
: 'a'..'z'
| 'A'..'Z'
;
fragment
Digit
: '0'..'9'
;
fragment
Alnum
: Letter
| Digit
;
// syntactic Elements
IntegerPositiveLiteral
: Digit+
;
IntegerNegativeLiteral
: '-' Digit+
;
DoubleLiteral
: Digit+ '.' Digit+;
Identifier
: (Letter | Alnum) (Alnum | '_' | '-' )*
;
// literals
StringLiteral
:
'\'' (~'\'')* '\'' ( '\'' (~'\'')* '\'' )*
;
//
// syntactic elements
//
SEMICOLON
: ';'
;
WS
: (' '|'\r'|'\t'|'\n') {$channel=HIDDEN;} // whitepace
;
COMMENT
: '--' (~('\n'|'\r'))* { $channel=HIDDEN; }
| '/*' (options {greedy=false;} : .)* '*/' { $channel=HIDDEN; }
;