Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ libcypher_parser_la_SOURCES = \
ast_on_match.c \
ast_order_by.c \
ast_parameter.c \
ast_path_pattern.c \
ast_path_pattern_expression.c \
ast_path_pattern_alternative.c \
ast_path_pattern_base.c \
ast_path_pattern_edge.c \
ast_path_pattern_reference.c \
ast_pattern.c \
ast_pattern_comprehension.c \
ast_pattern_path.c \
Expand Down
18 changes: 18 additions & 0 deletions lib/src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ struct cypher_astnode_vts
const struct cypher_astnode_vt *pattern_path;
const struct cypher_astnode_vt *node_pattern;
const struct cypher_astnode_vt *rel_pattern;
const struct cypher_astnode_vt *path_pattern;
const struct cypher_astnode_vt *path_pattern_expression;
const struct cypher_astnode_vt *path_pattern_alternative;
const struct cypher_astnode_vt *path_pattern_base;
const struct cypher_astnode_vt *path_pattern_edge;
const struct cypher_astnode_vt *path_pattern_reference;
const struct cypher_astnode_vt *range;
const struct cypher_astnode_vt *command;
const struct cypher_astnode_vt *comment;
Expand Down Expand Up @@ -242,6 +248,12 @@ static const struct cypher_astnode_vts cypher_astnode_vts =
.pattern_path = &cypher_pattern_path_astnode_vt,
.node_pattern = &cypher_node_pattern_astnode_vt,
.rel_pattern = &cypher_rel_pattern_astnode_vt,
.path_pattern = &cypher_path_pattern_astnode_vt,
.path_pattern_expression = &cypher_path_pattern_expression_astnode_vt,
.path_pattern_alternative = &cypher_path_pattern_alternative_astnode_vt,
.path_pattern_base = &cypher_path_pattern_base_astnode_vt,
.path_pattern_edge = &cypher_path_pattern_edge_astnode_vt,
.path_pattern_reference = &cypher_path_pattern_reference_astnode_vt,
.range = &cypher_range_astnode_vt,
.command = &cypher_command_astnode_vt,
.line_comment = &cypher_line_comment_astnode_vt,
Expand Down Expand Up @@ -369,6 +381,12 @@ const uint8_t CYPHER_AST_SHORTEST_PATH = VT_OFFSET(shortest_path);
const uint8_t CYPHER_AST_PATTERN_PATH = VT_OFFSET(pattern_path);
const uint8_t CYPHER_AST_NODE_PATTERN = VT_OFFSET(node_pattern);
const uint8_t CYPHER_AST_REL_PATTERN = VT_OFFSET(rel_pattern);
const uint8_t CYPHER_AST_PATH_PATTERN = VT_OFFSET(path_pattern);
const uint8_t CYPHER_AST_PATH_PATTERN_EXPRESSION = VT_OFFSET(path_pattern_expression);
const uint8_t CYPHER_AST_PATH_PATTERN_ALTERNATIVE = VT_OFFSET(path_pattern_alternative);
const uint8_t CYPHER_AST_PATH_PATTERN_BASE = VT_OFFSET(path_pattern_base);
const uint8_t CYPHER_AST_PATH_PATTERN_EDGE = VT_OFFSET(path_pattern_edge);
const uint8_t CYPHER_AST_PATH_PATTERN_REFERENCE = VT_OFFSET(path_pattern_reference);
const uint8_t CYPHER_AST_RANGE = VT_OFFSET(range);
const uint8_t CYPHER_AST_COMMAND = VT_OFFSET(command);
const uint8_t CYPHER_AST_COMMENT = VT_OFFSET(comment);
Expand Down
30 changes: 26 additions & 4 deletions lib/src/ast_named_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct named_path
cypher_pattern_path_astnode_t _pattern_path_astnode;
const cypher_astnode_t *identifier;
const cypher_astnode_t *path;
const cypher_astnode_t *condition;
};


Expand Down Expand Up @@ -53,7 +54,7 @@ static const struct cypher_pattern_path_astnode_vt pp_vt =


cypher_astnode_t *cypher_ast_named_path(const cypher_astnode_t *identifier,
const cypher_astnode_t *path, cypher_astnode_t **children,
const cypher_astnode_t *path, const cypher_astnode_t *condition, cypher_astnode_t **children,
unsigned int nchildren, struct cypher_input_range range)
{
REQUIRE_CHILD(children, nchildren, identifier, CYPHER_AST_IDENTIFIER, NULL);
Expand All @@ -72,6 +73,7 @@ cypher_astnode_t *cypher_ast_named_path(const cypher_astnode_t *identifier,
}
node->identifier = identifier;
node->path = path;
node->condition = condition;
return &(node->_pattern_path_astnode._astnode);
}

Expand All @@ -87,8 +89,9 @@ cypher_astnode_t *clone(const cypher_astnode_t *self,

cypher_astnode_t *identifier = children[child_index(self, node->identifier)];
cypher_astnode_t *path = children[child_index(self, node->path)];
cypher_astnode_t *condition = children[child_index(self, node->condition)];

return cypher_ast_named_path(identifier, path, children, self->nchildren,
return cypher_ast_named_path(identifier, path, condition, children, self->nchildren,
self->range);
}

Expand Down Expand Up @@ -116,6 +119,16 @@ const cypher_astnode_t *cypher_ast_named_path_get_path(
return node->path;
}

const cypher_astnode_t *cypher_ast_named_path_get_condition(
const cypher_astnode_t *astnode)
{
REQUIRE_TYPE(astnode, CYPHER_AST_NAMED_PATH, NULL);
const cypher_pattern_path_astnode_t *ppnode =
container_of(astnode, cypher_pattern_path_astnode_t, _astnode);
struct named_path *node =
container_of(ppnode, struct named_path, _pattern_path_astnode);
return node->condition;
}

unsigned int nelements(const cypher_pattern_path_astnode_t *self)
{
Expand All @@ -141,6 +154,15 @@ ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size)
container_of(self, cypher_pattern_path_astnode_t, _astnode);
struct named_path *node =
container_of(ppnode, struct named_path, _pattern_path_astnode);
return snprintf(str, size, "@%d = @%d", node->identifier->ordinal,
node->path->ordinal);
if (node->condition != NULL)
{
return snprintf(str, size, "@%d = @%d WHERE @%d", node->identifier->ordinal,
node->path->ordinal, node->condition->ordinal);
}

else
{
return snprintf(str, size, "@%d = @%d", node->identifier->ordinal,
node->path->ordinal);
}
}
127 changes: 127 additions & 0 deletions lib/src/ast_path_pattern.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* vi:set ts=4 sw=4 expandtab:
*
* Copyright 2016, Chris Leishman (http://github.com/cleishm)
*
* Licensed 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.
*/
#include "../../config.h"
#include "astnode.h"
#include "util.h"
#include <assert.h>

struct path_pattern
{
cypher_astnode_t _astnode;
const cypher_astnode_t *expression;
enum cypher_rel_direction direction;
};

static cypher_astnode_t *clone(const cypher_astnode_t *self,
cypher_astnode_t **children);
static ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size);

const struct cypher_astnode_vt cypher_path_pattern_astnode_vt =
{ .name = "path pattern",
.detailstr = detailstr,
.release = cypher_astnode_release,
.clone = clone };

cypher_astnode_t *cypher_ast_path_pattern(const cypher_astnode_t *expression,
enum cypher_rel_direction direction, cypher_astnode_t **children, unsigned int nchildren,
struct cypher_input_range range)
{
struct path_pattern *node = calloc(1, sizeof(struct path_pattern));
if (node == NULL)
{
return NULL;
}
if (cypher_astnode_init(&(node->_astnode), CYPHER_AST_PATH_PATTERN,
children, nchildren, range))
{
goto cleanup;
}
node->expression = expression;
node->direction = direction;
return &(node->_astnode);

int errsv;
cleanup:
errsv = errno;
free(node);
errno = errsv;
return NULL;
}

cypher_astnode_t *clone(const cypher_astnode_t *self,
cypher_astnode_t **children)
{
/**REQUIRE_TYPE(self, CYPHER_AST_PATH_PATTERN, NULL);*/
struct path_pattern *node = container_of(self, struct path_pattern, _astnode);

cypher_astnode_t *clone = cypher_ast_path_pattern(node->expression,
node->direction, children, self->nchildren,
self->range);
return clone;
}

const cypher_astnode_t *cypher_ast_path_pattern_get_expression(
const cypher_astnode_t *astnode)
{
struct path_pattern *node =
container_of(astnode, struct path_pattern, _astnode);
return node->expression;
}

enum cypher_rel_direction cypher_ast_path_pattern_get_direction(
const cypher_astnode_t *astnode)
{
struct path_pattern *node =
container_of(astnode, struct path_pattern, _astnode);
return node->direction;
}

ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size)
{
struct path_pattern *node = container_of(self, struct path_pattern, _astnode);

size_t n = 0;
ssize_t r = snprintf(str, size, "%s-/",
(node->direction == CYPHER_REL_INBOUND)? "<" : "");
if (r < 0)
{
return -1;
}
n += r;

if (node->expression != NULL)
{
r = snprintf(str+n, (n < size)? size-n : 0, "@%u",
node->expression->ordinal);
if (r < 0)
{
return -1;
}
n += r;
}

r = snprintf(str+n, (n < size)? size-n : 0, "/-%s",
(node->direction == CYPHER_REL_OUTBOUND)? ">" : "");

if (r < 0)
{
return -1;
}
n += r;

return n;
}
89 changes: 89 additions & 0 deletions lib/src/ast_path_pattern_alternative.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include "astnode.h"

struct path_pattern_alternative
{
cypher_astnode_t _astnode;
size_t nelements;
const cypher_astnode_t *elements[];
};

static cypher_astnode_t *clone(const cypher_astnode_t *self,
cypher_astnode_t **children);
static ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size);

const struct cypher_astnode_vt cypher_path_pattern_alternative_astnode_vt =
{
.name = "alternative",
.detailstr = detailstr,
.release = cypher_astnode_release,
.clone = clone };

cypher_astnode_t *cypher_ast_path_pattern_alternative(cypher_astnode_t * const *elements, unsigned int nelements,
cypher_astnode_t **children, unsigned int nchildren, struct cypher_input_range range)
{
struct path_pattern_alternative *node = calloc(1, sizeof(struct path_pattern_alternative) +
nelements * sizeof(cypher_astnode_t *));
if (node == NULL)
{
return NULL;
}

if (cypher_astnode_init(&(node->_astnode), CYPHER_AST_PATH_PATTERN_ALTERNATIVE,
children, nchildren, range))
{
goto cleanup;
}

memcpy(node->elements, elements, nelements * sizeof(cypher_astnode_t *));
node->nelements = nelements;
return &(node->_astnode);

int errsv;
cleanup:
errsv = errno;
free(node);
errno = errsv;
return NULL;
}

unsigned int cypher_ast_path_pattern_alternative_get_nelements(const cypher_astnode_t *astnode) {
REQUIRE_TYPE(astnode, CYPHER_AST_PATH_PATTERN_ALTERNATIVE, NULL);
struct path_pattern_alternative *node =
container_of(astnode, struct path_pattern_alternative, _astnode);
return node->nelements;
}

const cypher_astnode_t *cypher_ast_path_pattern_alternative_get_element(
const cypher_astnode_t *astnode, unsigned int index)
{
REQUIRE_TYPE(astnode, CYPHER_AST_PATH_PATTERN_ALTERNATIVE, NULL);
struct path_pattern_alternative *node =
container_of(astnode, struct path_pattern_alternative, _astnode);
return node->elements[index];
}

cypher_astnode_t *clone(const cypher_astnode_t *self, cypher_astnode_t **children)
{
/**REQUIRE_TYPE(self, CYPHER_AST_PATH_PATTERN, NULL);*/
struct path_pattern_alternative *node = container_of(self, struct path_pattern_alternative, _astnode);

cypher_astnode_t **elements =
calloc(node->nelements, sizeof(cypher_astnode_t *));
if (elements == NULL)
{
return NULL;
}
for (unsigned int i = 0; i < node->nelements; ++i)
{
elements[i] = children[child_index(self, node->elements[i])];
}

cypher_astnode_t *clone = cypher_ast_path_pattern_alternative(elements, node->nelements, children, self->nchildren,
self->range);
return clone;
}

ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size) {
const struct path_pattern_alternative *alt = (const struct path_pattern_alternative *) self;
return snprintf(str, size, "Alt, elems: %ld", alt->nelements);
}
Loading