Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path patterns support #26

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cab8981
Started work on supporting path patterns
Timur-Zinnatulin Dec 25, 2019
9796584
Minor fix to PATTERN_PATH printing result
Timur-Zinnatulin Feb 26, 2020
a336dda
Temporary improvements to structure
Timur-Zinnatulin Mar 16, 2020
e3cd38c
Fixed the mistakes I made yesterday
Timur-Zinnatulin Mar 17, 2020
090ab60
add path pattern alternative
simpletonDL Mar 19, 2020
0a34a6f
add path ast_path_pattern_alternative
simpletonDL Mar 19, 2020
221eb6f
Added path expression node support
Timur-Zinnatulin Mar 19, 2020
f1fb4e5
Unbloated path_pattern
Timur-Zinnatulin Mar 19, 2020
f2108ac
add path base ast node
simpletonDL Mar 22, 2020
3d00ad3
Added Named-Path-Predicate support
Timur-Zinnatulin Mar 24, 2020
d813f54
add path edge ast node
simpletonDL Mar 26, 2020
09d97f4
add some getters
simpletonDL Mar 26, 2020
fdb9a6d
add path reference ast node
simpletonDL Mar 28, 2020
689f6ec
Moved named-path-predicate to query clauses
Timur-Zinnatulin Mar 29, 2020
6612e13
Finished all the necessary work on the parser.
Timur-Zinnatulin Mar 29, 2020
e8593da
Added one test for new syntax
Timur-Zinnatulin Apr 14, 2020
9317257
Added multiple alternatives test.
Timur-Zinnatulin Apr 14, 2020
8fa639a
Added more path pattern tests and fixed ast output
Timur-Zinnatulin Apr 16, 2020
b2c7514
Pretty much finished writing path pattern tests
Timur-Zinnatulin Apr 16, 2020
8ff19f6
Added missing comments.
Timur-Zinnatulin Apr 16, 2020
4bb9d7f
Added "+" and "?" support
Timur-Zinnatulin May 9, 2020
9c2e732
Fixed the biggest bug of them all
Timur-Zinnatulin May 9, 2020
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
7 changes: 7 additions & 0 deletions lib/src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ libcypher_parser_la_SOURCES = \
ast_on_match.c \
ast_order_by.c \
ast_parameter.c \
ast_path_pattern.c \
ast_path_pattern_any.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
21 changes: 21 additions & 0 deletions lib/src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ 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_any;
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 +249,13 @@ 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_any = &cypher_path_pattern_any_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 +383,13 @@ 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_ANY = VT_OFFSET(path_pattern_any);
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);
}
}
111 changes: 111 additions & 0 deletions lib/src/ast_path_pattern.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#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;
}
115 changes: 115 additions & 0 deletions lib/src/ast_path_pattern_alternative.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include "../../config.h"
#include "astnode.h"
#include "util.h"
#include <assert.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_ALTERNATIVE, 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) {
struct path_pattern_alternative *node = container_of(self, struct path_pattern_alternative, _astnode);

size_t n = 0;
for (unsigned int i = 0; i < node->nelements; ++i)
{
ssize_t r;
if (i < node->nelements - 1)
{
r = snprintf(str+n, (n < size)? size-n : 0, "@%u | ",
node->elements[i]->ordinal);
}
else
{
r = snprintf(str+n, (n < size)? size-n : 0, "@%u",
node->elements[i]->ordinal);
}

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

return n;
}
Loading