mirror of https://gitee.com/bigwinds/arangodb
900 lines
18 KiB
Plaintext
900 lines
18 KiB
Plaintext
|
|
%define api.pure
|
|
%name-prefix="Ahuacatl"
|
|
%locations
|
|
%defines
|
|
%parse-param { TRI_aql_context_t* const context }
|
|
%lex-param { void* scanner }
|
|
%error-verbose
|
|
|
|
%{
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <BasicsC/common.h>
|
|
#include <BasicsC/conversions.h>
|
|
#include <BasicsC/strings.h>
|
|
|
|
#include "Ahuacatl/ahuacatl-ast-node.h"
|
|
#include "Ahuacatl/ahuacatl-context.h"
|
|
#include "Ahuacatl/ahuacatl-error.h"
|
|
#include "Ahuacatl/ahuacatl-parser.h"
|
|
#include "Ahuacatl/ahuacatl-parser-functions.h"
|
|
%}
|
|
|
|
%union {
|
|
TRI_aql_node_t* node;
|
|
char* strval;
|
|
bool boolval;
|
|
int64_t intval;
|
|
}
|
|
|
|
%{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief forward for lexer function defined in ahuacatl-tokens.l
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int Ahuacatllex (YYSTYPE*, YYLTYPE*, void*);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief register parse error
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Ahuacatlerror (YYLTYPE* locp, TRI_aql_context_t* const context, const char* err) {
|
|
TRI_SetErrorParseAql(context, err, locp->first_line, locp->first_column);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief shortcut macro for signalling out of memory
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define ABORT_OOM \
|
|
TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); \
|
|
YYABORT;
|
|
|
|
#define scanner context->_parser->_scanner
|
|
%}
|
|
|
|
/* define tokens and "nice" token names */
|
|
%token T_FOR "FOR declaration"
|
|
%token T_LET "LET declaration"
|
|
%token T_FILTER "FILTER declaration"
|
|
%token T_RETURN "RETURN declaration"
|
|
%token T_COLLECT "COLLECT declaration"
|
|
%token T_SORT "SORT declaration"
|
|
%token T_LIMIT "LIMIT declaration"
|
|
|
|
%token T_ASC "ASC keyword"
|
|
%token T_DESC "DESC keyword"
|
|
%token T_IN "IN keyword"
|
|
%token T_INTO "INTO keyword"
|
|
|
|
%token T_NULL "null"
|
|
%token T_TRUE "true"
|
|
%token T_FALSE "false"
|
|
%token T_STRING "identifier"
|
|
%token T_QUOTED_STRING "quoted string"
|
|
%token T_NUMBER "number"
|
|
%token T_PARAMETER "bind parameter"
|
|
|
|
%token T_ASSIGN "assignment"
|
|
|
|
%token T_NOT "not operator"
|
|
%token T_AND "and operator"
|
|
%token T_OR "or operator"
|
|
|
|
%token T_EQ "== operator"
|
|
%token T_NE "!= operator"
|
|
%token T_LT "< operator"
|
|
%token T_GT "> operator"
|
|
%token T_LE "<= operator"
|
|
%token T_GE ">= operator"
|
|
|
|
%token T_PLUS "+ operator"
|
|
%token T_MINUS "- operator"
|
|
%token T_TIMES "* operator"
|
|
%token T_DIV "/ operator"
|
|
%token T_MOD "% operator"
|
|
|
|
%token T_QUESTION "?"
|
|
%token T_COLON ":"
|
|
|
|
%token T_COMMA ","
|
|
%token T_OPEN "("
|
|
%token T_CLOSE ")"
|
|
%token T_DOC_OPEN "{"
|
|
%token T_DOC_CLOSE "}"
|
|
%token T_LIST_OPEN "["
|
|
%token T_LIST_CLOSE "]"
|
|
|
|
%token T_END 0 "end of query string"
|
|
|
|
|
|
/* define operator precedence */
|
|
%left T_COMMA
|
|
%right T_ASSIGN
|
|
%right T_QUESTION T_COLON
|
|
%left T_OR
|
|
%left T_AND
|
|
%left T_EQ T_NE
|
|
%left T_IN
|
|
%left T_LT T_GT T_LE T_GE
|
|
%left T_PLUS T_MINUS
|
|
%left T_TIMES T_DIV T_MOD
|
|
%right UMINUS UPLUS T_NOT
|
|
%left FUNCCALL
|
|
%left REFERENCE
|
|
%left INDEXED
|
|
|
|
/* define token return types */
|
|
%type <strval> T_STRING
|
|
%type <strval> T_QUOTED_STRING
|
|
%type <strval> T_NUMBER
|
|
%type <strval> T_PARAMETER;
|
|
|
|
%type <node> query;
|
|
%type <node> for_statement;
|
|
%type <node> filter_statement;
|
|
%type <node> let_statement;
|
|
%type <node> collect_statement;
|
|
%type <node> sort_statement;
|
|
%type <node> sort_list;
|
|
%type <node> sort_element;
|
|
%type <boolval> sort_direction;
|
|
%type <node> limit_statement;
|
|
%type <node> return_statement;
|
|
%type <node> collect_list;
|
|
%type <node> collect_element;
|
|
%type <strval> optional_into;
|
|
%type <node> expression;
|
|
%type <node> operator_unary;
|
|
%type <node> operator_binary;
|
|
%type <node> operator_ternary;
|
|
%type <node> optional_function_call_arguments;
|
|
%type <node> function_arguments_list;
|
|
%type <node> compound_type;
|
|
%type <node> list;
|
|
%type <node> optional_list_elements;
|
|
%type <node> list_elements_list;
|
|
%type <node> array;
|
|
%type <node> optional_array_elements;
|
|
%type <node> array_elements_list;
|
|
%type <node> array_element;
|
|
%type <strval> array_element_name;
|
|
%type <node> reference;
|
|
%type <node> expansion;
|
|
%type <node> atomic_value;
|
|
%type <node> value_literal;
|
|
%type <node> bind_parameter;
|
|
%type <strval> variable_name;
|
|
%type <intval> signed_number;
|
|
|
|
|
|
/* define start token of language */
|
|
%start query
|
|
|
|
%%
|
|
|
|
query:
|
|
{
|
|
// a query or a sub-query always starts a new scope
|
|
if (!TRI_StartScopeContextAql(context)) {
|
|
ABORT_OOM
|
|
}
|
|
} optional_statement_block_statements return_statement {
|
|
// end the scope
|
|
$$ = (TRI_aql_node_t*) TRI_GetFirstStatementAql(context);
|
|
|
|
TRI_EndScopeContextAql(context);
|
|
}
|
|
;
|
|
|
|
optional_statement_block_statements:
|
|
/* empty */ {
|
|
}
|
|
| optional_statement_block_statements statement_block_statement {
|
|
}
|
|
;
|
|
|
|
statement_block_statement:
|
|
for_statement {
|
|
}
|
|
| let_statement {
|
|
}
|
|
| filter_statement {
|
|
}
|
|
| collect_statement {
|
|
}
|
|
| sort_statement {
|
|
}
|
|
| limit_statement {
|
|
}
|
|
|
|
for_statement:
|
|
T_FOR variable_name T_IN expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeForAql(context, $2, $4);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
filter_statement:
|
|
T_FILTER expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeFilterAql(context, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
let_statement:
|
|
T_LET variable_name {
|
|
if (!TRI_PushStackParseAql(context, $2) || !TRI_StartScopeContextAql(context)) {
|
|
ABORT_OOM
|
|
}
|
|
} T_ASSIGN T_OPEN expression T_CLOSE {
|
|
TRI_aql_node_t* node;
|
|
|
|
TRI_EndScopeContextAql(context);
|
|
|
|
node = TRI_CreateNodeAssignAql(context, TRI_PopStackParseAql(context), $6);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
collect_statement:
|
|
T_COLLECT {
|
|
TRI_aql_node_t* node = TRI_CreateNodeListAql(context);
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
TRI_PushStackParseAql(context, node);
|
|
} collect_list optional_into {
|
|
TRI_aql_node_t* node = TRI_CreateNodeCollectAql(context, TRI_PopStackParseAql(context), $4);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
collect_list:
|
|
collect_element {
|
|
}
|
|
| collect_list T_COMMA collect_element {
|
|
}
|
|
;
|
|
|
|
collect_element:
|
|
variable_name T_ASSIGN expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeAssignAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_PushListAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| expression {
|
|
if (!TRI_PushListAql(context, $1)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
;
|
|
|
|
optional_into:
|
|
/* empty */ {
|
|
$$ = NULL;
|
|
}
|
|
| T_INTO variable_name {
|
|
$$ = $2;
|
|
}
|
|
;
|
|
|
|
sort_statement:
|
|
T_SORT {
|
|
TRI_aql_node_t* node = TRI_CreateNodeListAql(context);
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
TRI_PushStackParseAql(context, node);
|
|
} sort_list {
|
|
TRI_aql_node_t* list = TRI_PopStackParseAql(context);
|
|
TRI_aql_node_t* node = TRI_CreateNodeSortAql(context, list);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
sort_list:
|
|
sort_element {
|
|
if (!TRI_PushListAql(context, $1)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| sort_list T_COMMA sort_element {
|
|
if (!TRI_PushListAql(context, $3)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
;
|
|
|
|
sort_element:
|
|
expression sort_direction {
|
|
TRI_aql_node_t* node = TRI_CreateNodeSortElementAql(context, $1, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
sort_direction:
|
|
/* empty */ {
|
|
$$ = true;
|
|
}
|
|
| T_ASC {
|
|
$$ = true;
|
|
}
|
|
| T_DESC {
|
|
$$ = false;
|
|
}
|
|
;
|
|
|
|
limit_statement:
|
|
T_LIMIT signed_number {
|
|
TRI_aql_node_t* node = TRI_CreateNodeLimitAql(context, TRI_CreateNodeValueIntAql(context, 0), TRI_CreateNodeValueIntAql(context, $2));
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_LIMIT signed_number T_COMMA signed_number {
|
|
TRI_aql_node_t* node = TRI_CreateNodeLimitAql(context, TRI_CreateNodeValueIntAql(context, $2), TRI_CreateNodeValueIntAql(context, $4));
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
return_statement:
|
|
T_RETURN expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeReturnAql(context, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
if (!TRI_AddStatementAql(context, node)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
|
|
expression:
|
|
T_OPEN expression T_CLOSE {
|
|
$$ = $2;
|
|
}
|
|
| T_OPEN query T_CLOSE {
|
|
TRI_aql_node_t* node = TRI_CreateNodeSubqueryAql(context, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| operator_unary {
|
|
$$ = $1;
|
|
}
|
|
| operator_binary {
|
|
$$ = $1;
|
|
}
|
|
| operator_ternary {
|
|
$$ = $1;
|
|
}
|
|
| T_STRING {
|
|
TRI_aql_node_t* node;
|
|
|
|
if (!TRI_PushStackParseAql(context, $1)) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = TRI_CreateNodeListAql(context);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
TRI_PushStackParseAql(context, node);
|
|
} T_OPEN optional_function_call_arguments T_CLOSE %prec FUNCCALL {
|
|
TRI_aql_node_t* list = TRI_PopStackParseAql(context);
|
|
TRI_aql_node_t* node = TRI_CreateNodeFcallAql(context, TRI_PopStackParseAql(context), list);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| compound_type {
|
|
$$ = $1;
|
|
}
|
|
| atomic_value {
|
|
$$ = $1;
|
|
}
|
|
| reference {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
operator_unary:
|
|
T_PLUS expression %prec UPLUS {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorUnaryPlusAql(context, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_MINUS expression %prec UMINUS {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorUnaryMinusAql(context, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_NOT expression %prec T_NOT {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorUnaryNotAql(context, $2);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
operator_binary:
|
|
expression T_OR expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryOrAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_AND expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryAndAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_PLUS expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryPlusAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_MINUS expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryMinusAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_TIMES expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryTimesAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_DIV expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryDivAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_MOD expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryModAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_EQ expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryEqAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_NE expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryNeAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_LT expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryLtAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_GT expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryGtAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_LE expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryLeAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_GE expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryGeAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| expression T_IN expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorBinaryInAql(context, $1, $3);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
operator_ternary:
|
|
expression T_QUESTION expression T_COLON expression {
|
|
TRI_aql_node_t* node = TRI_CreateNodeOperatorTernaryAql(context, $1, $3, $5);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
optional_function_call_arguments:
|
|
/* empty */ {
|
|
}
|
|
| function_arguments_list {
|
|
}
|
|
;
|
|
|
|
function_arguments_list:
|
|
expression {
|
|
TRI_PushListAql(context, $1);
|
|
}
|
|
| function_arguments_list T_COMMA expression {
|
|
TRI_PushListAql(context, $3);
|
|
}
|
|
;
|
|
|
|
compound_type:
|
|
list {
|
|
$$ = $1;
|
|
}
|
|
| array {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
list:
|
|
T_LIST_OPEN {
|
|
TRI_aql_node_t* node = TRI_CreateNodeListAql(context);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
TRI_PushStackParseAql(context, node);
|
|
} optional_list_elements T_LIST_CLOSE {
|
|
$$ = TRI_PopStackParseAql(context);
|
|
}
|
|
;
|
|
|
|
optional_list_elements:
|
|
/* empty */ {
|
|
}
|
|
| list_elements_list {
|
|
}
|
|
;
|
|
|
|
list_elements_list:
|
|
expression {
|
|
if (!TRI_PushListAql(context, $1)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| list_elements_list T_COMMA expression {
|
|
if (!TRI_PushListAql(context, $3)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
;
|
|
|
|
array:
|
|
T_DOC_OPEN {
|
|
TRI_aql_node_t* node = TRI_CreateNodeArrayAql(context);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
TRI_PushStackParseAql(context, node);
|
|
} optional_array_elements T_DOC_CLOSE {
|
|
$$ = TRI_PopStackParseAql(context);
|
|
}
|
|
;
|
|
|
|
optional_array_elements:
|
|
/* empty */ {
|
|
}
|
|
| array_elements_list {
|
|
}
|
|
;
|
|
|
|
array_elements_list:
|
|
array_element {
|
|
}
|
|
| array_elements_list T_COMMA array_element {
|
|
}
|
|
;
|
|
|
|
array_element:
|
|
array_element_name T_COLON expression {
|
|
if (!TRI_PushArrayAql(context, $1, $3)) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
;
|
|
|
|
reference:
|
|
T_STRING {
|
|
// variable or collection
|
|
TRI_aql_node_t* node;
|
|
|
|
if (TRI_VariableExistsAql(context, $1)) {
|
|
node = TRI_CreateNodeReferenceAql(context, $1);
|
|
}
|
|
else {
|
|
node = TRI_CreateNodeCollectionAql(context, $1);
|
|
}
|
|
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| reference T_LIST_OPEN expression T_LIST_CLOSE %prec INDEXED {
|
|
// variable[]
|
|
$$ = TRI_CreateNodeIndexedAql(context, $1, $3);
|
|
if (!$$) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| reference T_LIST_OPEN T_TIMES T_LIST_CLOSE '.' expansion %prec INDEXED {
|
|
// variable[*]
|
|
$$ = TRI_CreateNodeExpandAql(context, $1, $6);
|
|
if (!$$) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| reference '.' T_STRING %prec REFERENCE {
|
|
// variable.reference
|
|
$$ = TRI_CreateNodeAttributeAccessAql(context, $1, $3);
|
|
if (!$$) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
;
|
|
|
|
expansion:
|
|
T_STRING {
|
|
// reference
|
|
$$ = TRI_CreateNodeAttributeAql(context, $1);
|
|
if (!$$) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| expansion T_LIST_OPEN expression T_LIST_CLOSE %prec INDEXED {
|
|
// variable[]
|
|
$$ = TRI_CreateNodeIndexedAql(context, $1, $3);
|
|
if (!$$) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
| expansion '.' T_STRING %prec REFERENCE {
|
|
// variable.variable
|
|
$$ = TRI_CreateNodeAttributeAccessAql(context, $1, $3);
|
|
if (!$$) {
|
|
ABORT_OOM
|
|
}
|
|
}
|
|
;
|
|
|
|
atomic_value:
|
|
value_literal {
|
|
$$ = $1;
|
|
}
|
|
| bind_parameter {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
value_literal:
|
|
T_QUOTED_STRING {
|
|
TRI_aql_node_t* node = TRI_CreateNodeValueStringAql(context, $1);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_NUMBER {
|
|
TRI_aql_node_t* node;
|
|
|
|
if (!$1) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
node = TRI_CreateNodeValueDoubleAql(context, TRI_DoubleString($1));
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_NULL {
|
|
TRI_aql_node_t* node = TRI_CreateNodeValueNullAql(context);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_TRUE {
|
|
TRI_aql_node_t* node = TRI_CreateNodeValueBoolAql(context, true);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
| T_FALSE {
|
|
TRI_aql_node_t* node = TRI_CreateNodeValueBoolAql(context, false);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
bind_parameter:
|
|
T_PARAMETER {
|
|
TRI_aql_node_t* node = TRI_CreateNodeParameterAql(context, $1);
|
|
if (!node) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = node;
|
|
}
|
|
;
|
|
|
|
array_element_name:
|
|
T_STRING {
|
|
if (!$1) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = $1;
|
|
}
|
|
| T_QUOTED_STRING {
|
|
if (!$1) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = $1;
|
|
}
|
|
|
|
variable_name:
|
|
T_STRING {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
signed_number:
|
|
T_NUMBER {
|
|
if (!$1) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = TRI_Int64String($1);
|
|
}
|
|
| '-' T_NUMBER {
|
|
if (!$2) {
|
|
ABORT_OOM
|
|
}
|
|
|
|
$$ = - TRI_Int64String($2);
|
|
}
|
|
;
|
|
|