Skip to content

Support float literals: Nan, Inf, Infinity #23

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
2 changes: 2 additions & 0 deletions lib/src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ libcypher_parser_la_SOURCES = \
ast_function_name.c \
ast_identifier.c \
ast_index_name.c \
ast_inf.c \
ast_integer.c \
ast_label.c \
ast_labels_operator.c \
Expand All @@ -57,6 +58,7 @@ libcypher_parser_la_SOURCES = \
ast_merge_action.c \
ast_merge_properties.c \
ast_named_path.c \
ast_nan.c \
ast_node_id_lookup.c \
ast_node_index_lookup.c \
ast_node_index_query.c \
Expand Down
6 changes: 6 additions & 0 deletions lib/src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ struct cypher_astnode_vts
const struct cypher_astnode_vt *true_literal;
const struct cypher_astnode_vt *false_literal;
const struct cypher_astnode_vt *null_literal;
const struct cypher_astnode_vt *nan_literal;
const struct cypher_astnode_vt *inf_literal;
const struct cypher_astnode_vt *label;
const struct cypher_astnode_vt *reltype;
const struct cypher_astnode_vt *prop_name;
Expand Down Expand Up @@ -232,6 +234,8 @@ static const struct cypher_astnode_vts cypher_astnode_vts =
.true_literal = &cypher_true_astnode_vt,
.false_literal = &cypher_false_astnode_vt,
.null_literal = &cypher_null_astnode_vt,
.nan_literal = &cypher_nan_astnode_vt,
.inf_literal = &cypher_inf_astnode_vt,
.label = &cypher_label_astnode_vt,
.reltype = &cypher_reltype_astnode_vt,
.prop_name = &cypher_prop_name_astnode_vt,
Expand Down Expand Up @@ -361,6 +365,8 @@ const uint8_t CYPHER_AST_BOOLEAN = VT_OFFSET(boolean_literal);
const uint8_t CYPHER_AST_TRUE = VT_OFFSET(true_literal);
const uint8_t CYPHER_AST_FALSE = VT_OFFSET(false_literal);
const uint8_t CYPHER_AST_NULL = VT_OFFSET(null_literal);
const uint8_t CYPHER_AST_NAN = VT_OFFSET(nan_literal);
const uint8_t CYPHER_AST_INF = VT_OFFSET(inf_literal);
const uint8_t CYPHER_AST_LABEL = VT_OFFSET(label);
const uint8_t CYPHER_AST_RELTYPE = VT_OFFSET(reltype);
const uint8_t CYPHER_AST_PROP_NAME = VT_OFFSET(prop_name);
Expand Down
80 changes: 80 additions & 0 deletions lib/src/ast_inf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* 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 "operators.h"
#include "util.h"
#include <assert.h>


struct inf_literal
{
cypher_astnode_t _astnode;
};


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);


static const struct cypher_astnode_vt *parents[] =
{ &cypher_expression_astnode_vt };

const struct cypher_astnode_vt cypher_inf_astnode_vt =
{ .parents = parents,
.nparents = 1,
.name = "INF",
.detailstr = detailstr,
.release = cypher_astnode_release,
.clone = clone };


cypher_astnode_t *cypher_ast_inf(struct cypher_input_range range)
{
struct inf_literal *node = calloc(1, sizeof(struct inf_literal));
if (node == NULL)
{
return NULL;
}
if (cypher_astnode_init(&(node->_astnode), CYPHER_AST_INF,
NULL, 0, range))
{
free(node);
return NULL;
}
return &(node->_astnode);
}


cypher_astnode_t *clone(const cypher_astnode_t *self,
cypher_astnode_t **children)
{
REQUIRE_TYPE(self, CYPHER_AST_INF, NULL);
return cypher_ast_inf(self->range);
}


ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size)
{
REQUIRE_TYPE(self, CYPHER_AST_INF, -1);
if (size > 0)
{
str[0] = '\0';
}
return 0;
}
80 changes: 80 additions & 0 deletions lib/src/ast_nan.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/* 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 "operators.h"
#include "util.h"
#include <assert.h>


struct nan_literal
{
cypher_astnode_t _astnode;
};


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);


static const struct cypher_astnode_vt *parents[] =
{ &cypher_expression_astnode_vt };

const struct cypher_astnode_vt cypher_nan_astnode_vt =
{ .parents = parents,
.nparents = 1,
.name = "NAN",
.detailstr = detailstr,
.release = cypher_astnode_release,
.clone = clone };


cypher_astnode_t *cypher_ast_nan(struct cypher_input_range range)
{
struct nan_literal *node = calloc(1, sizeof(struct nan_literal));
if (node == NULL)
{
return NULL;
}
if (cypher_astnode_init(&(node->_astnode), CYPHER_AST_NAN,
NULL, 0, range))
{
free(node);
return NULL;
}
return &(node->_astnode);
}


cypher_astnode_t *clone(const cypher_astnode_t *self,
cypher_astnode_t **children)
{
REQUIRE_TYPE(self, CYPHER_AST_NAN, NULL);
return cypher_ast_nan(self->range);
}


ssize_t detailstr(const cypher_astnode_t *self, char *str, size_t size)
{
REQUIRE_TYPE(self, CYPHER_AST_NAN, -1);
if (size > 0)
{
str[0] = '\0';
}
return 0;
}
2 changes: 2 additions & 0 deletions lib/src/astnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ extern const struct cypher_astnode_vt cypher_boolean_astnode_vt;
extern const struct cypher_astnode_vt cypher_true_astnode_vt;
extern const struct cypher_astnode_vt cypher_false_astnode_vt;
extern const struct cypher_astnode_vt cypher_null_astnode_vt;
extern const struct cypher_astnode_vt cypher_nan_astnode_vt;
extern const struct cypher_astnode_vt cypher_inf_astnode_vt;
extern const struct cypher_astnode_vt cypher_label_astnode_vt;
extern const struct cypher_astnode_vt cypher_reltype_astnode_vt;
extern const struct cypher_astnode_vt cypher_prop_name_astnode_vt;
Expand Down
25 changes: 25 additions & 0 deletions lib/src/cypher-parser.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ extern const cypher_astnode_type_t CYPHER_AST_TRUE;
extern const cypher_astnode_type_t CYPHER_AST_FALSE;
/** Type for an AST NULL literal node. */
extern const cypher_astnode_type_t CYPHER_AST_NULL;
/** Type for an AST NAN literal node. */
extern const cypher_astnode_type_t CYPHER_AST_NAN;
/** Type for an AST INF literal node. */
extern const cypher_astnode_type_t CYPHER_AST_INF;
/** Type for an AST label node. */
extern const cypher_astnode_type_t CYPHER_AST_LABEL;
/** Type for an AST reltype node. */
Expand Down Expand Up @@ -4835,6 +4839,27 @@ cypher_astnode_t *cypher_ast_false(struct cypher_input_range range);
__cypherlang_must_check
cypher_astnode_t *cypher_ast_null(struct cypher_input_range range);

/**
* Construct a `CYPHER_AST_NAN` node.
*
* The node will also be an instance of `CYPHER_AST_EXPRESSION`.
*
* @param [range] The input range.
* @return An AST node, or NULL if an error occurs (errno will be set).
*/
__cypherlang_must_check
cypher_astnode_t *cypher_ast_nan(struct cypher_input_range range);

/**
* Construct a `CYPHER_AST_INF` node.
*
* The node will also be an instance of `CYPHER_AST_EXPRESSION`.
*
* @param [range] The input range.
* @return An AST node, or NULL if an error occurs (errno will be set).
*/
__cypherlang_must_check
cypher_astnode_t *cypher_ast_inf(struct cypher_input_range range);

/**
* Construct a `CYPHER_AST_LABEL` node.
Expand Down
19 changes: 19 additions & 0 deletions lib/src/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ static cypher_astnode_t *_true_literal(yycontext *yy);
static cypher_astnode_t *_false_literal(yycontext *yy);
#define null_literal() _null_literal(yy)
static cypher_astnode_t *_null_literal(yycontext *yy);
#define nan_literal() _nan_literal(yy)
static cypher_astnode_t *_nan_literal(yycontext *yy);
#define inf_literal() _inf_literal(yy)
static cypher_astnode_t *_inf_literal(yycontext *yy);
#define strbuf_label() _strbuf_label(yy)
static cypher_astnode_t *_strbuf_label(yycontext *yy);
#define strbuf_reltype() _strbuf_reltype(yy)
Expand Down Expand Up @@ -2808,6 +2812,21 @@ cypher_astnode_t *_null_literal(yycontext *yy)
return add_terminal(yy, cypher_ast_null(range));
}

cypher_astnode_t *_nan_literal(yycontext *yy)
{
assert(yy->prev_block != NULL &&
"An AST node can only be created immediately after a `>` in the grammar");
struct cypher_input_range range = yy->prev_block->range;
return add_terminal(yy, cypher_ast_nan(range));
}

cypher_astnode_t *_inf_literal(yycontext *yy)
{
assert(yy->prev_block != NULL &&
"An AST node can only be created immediately after a `>` in the grammar");
struct cypher_input_range range = yy->prev_block->range;
return add_terminal(yy, cypher_ast_inf(range));
}

cypher_astnode_t *_strbuf_label(yycontext *yy)
{
Expand Down
18 changes: 18 additions & 0 deletions lib/src/parser.leg
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ cypher-param-value =
true-literal
| false-literal
| null-literal
| nan-literal
| inf-literal
| infinity-literal
| string-literal
| collection-literal
| map-literal
Expand Down Expand Up @@ -522,6 +525,9 @@ atom =
true-literal
| false-literal
| null-literal
| nan-literal
| inf-literal
| infinity-literal
| string-literal
| float-literal
| integer-literal
Expand Down Expand Up @@ -715,6 +721,15 @@ false-literal =
null-literal =
< NULL > { $$ = null_literal(); }
-
nan-literal =
< NAN > { $$ = nan_literal(); }
-
inf-literal =
< INF > { $$ = inf_literal(); }
-
infinity-literal =
< INFINITY > { $$ = inf_literal(); }
-

parameter = _block_start_ { strbuf_reset(); }
( ( '$' - parameter-name ) ~{ERR("a parameter")}
Expand Down Expand Up @@ -1114,6 +1129,9 @@ FIELDTERMINATOR = ([Ff][Ii][Ee][Ll][Dd][Tt][Ee][Rr][Mm][Ii][Nn][Aa][Tt][Oo][Rr]
TRUE = ([Tt][Rr][Uu][Ee] WB) ~{ERR("TRUE")}
FALSE = ([Ff][Aa][Ll][Ss][Ee] WB) ~{ERR("FALSE")}
NULL = ([Nn][Uu][Ll][Ll] WB) ~{ERR("NULL")}
NAN = ([Nn][Aa][Nn] WB) ~{ERR("NAN")}
INF = ([Ii][Nn][Ff] WB) ~{ERR("INF")}
INFINITY = ([Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy] WB) ~{ERR("INFINITY")}

SHORTESTPATH = ([Ss][Hh][Oo][Rr][Tt][Ee][Ss][Tt][Pp][Aa][Tt][Hh] WB -)
~{ERR("shortestPath")}
Expand Down