Skip to content

Commit

Permalink
simpler solution:
Browse files Browse the repository at this point in the history
- do it only in the lexer: break up all problematic arrows
  • Loading branch information
peter authored and peter committed Jan 4, 2025
1 parent 25666ef commit 7273679
Show file tree
Hide file tree
Showing 5 changed files with 20,232 additions and 20,124 deletions.
96 changes: 21 additions & 75 deletions third_party/libpg_query/grammar/statements/pgq.y
Original file line number Diff line number Diff line change
Expand Up @@ -748,102 +748,48 @@ FullElementSpec:
}
;

StickyDash:
Op
{ /* DDB lexer may concatenate an arrow with + or * into an "operator" */
char *op = $1, *ok = NULL;
/* only <-, <->, -, -> are ok */
if (op[0] == '<') op++; /* also accept <-> */
if (op[0] == '-') {
ok = op + 1 + (op[1] == '>');
}
/* it may optionally be followed by a single * or + */
if (!ok || (ok[0] && ((ok[0] != '*' && ok[0] != '+') || ok[1]))) {
char msg[128];
snprintf(msg, 128, "PGQ expected an arrow instead of %s operator.", $1);
parser_yyerror(msg);
}
$$ = $1;
}


/* we allow spaces inside the arrows */
Arrow:
'-' '>'
{ $$ = "->"; }
|
'-'
{ $$ = "-"; }
|
StickyDash
{ $$ = $1; }
ArrowRight
{ $$ = $1; }
|
'<' LAMBDA_ARROW
{ $$ = "<->"; }
{ $$ = "<->"; }
|
'<' '-' '>'
{ $$ = "<->"; }
|
'<' StickyDash
{ char *op = $2;
if (op[0] == '<') {
parser_yyerror("PGQ does not allow < followed by < as edge operator");
}
$$ = (char*) ((op[1] == 0) ? "<-" :
(op[1] == '*') ? "<-*" :
(op[1] == '+') ? "<-+" :
(op[2] == '*') ? "<->*" :
(op[2] == '+') ? "<->+" : "<->");
}
{ $$ = "<->"; }
|
'<' '-'
{ $$ = "<-"; }
|
;

ArrowRight:
LAMBDA_ARROW
{ $$ = "->"; }
{ $$ = "->"; }
|
'-' '>'
{ $$ = "->"; }
|
'-'
{ $$ = "-"; }
;

ArrowLeft:
'-' '['
{ $$ = "-"; }
{ $$ = "-"; }
|
'<' '-' '['
{ $$ = "<-"; }
;

ArrowKleeneOptional:
Arrow KleeneOptional
{
PGSubPath *p = (PGSubPath*) $2;
char *op = $1;
int len = strlen(op);
int plus = (op[len-1] == '+');
int star = (op[len-1] == '*');
if (plus || star) { /* + or * was glued to the end of the arrow */
if (!p->single_bind || p->lower != 1 || p-> upper != 1) {
parser_yyerror("PGQ cannot accept + or * followed by another quantifier.");
} else {
p->single_bind = 0;
p->lower = plus;
p->upper = (1<<30);
}
}
p->path = (PGList*) op; /* return the arrow temporarily in 'path'.. */
$$ = (PGNode*) p;
}
;

EdgePattern:
ArrowLeft FullElementSpec ']' ArrowKleeneOptional
ArrowLeft FullElementSpec ']' ArrowRight KleeneOptional
{
PGSubPath *p = (PGSubPath*) $4;
PGSubPath *p = (PGSubPath*) $5;
char *left = $1;
char *dash = (char*) p->path;
char *dash = (char*) $4;
PGPathInfo* i = (PGPathInfo*) $2;
PGPathElement *n = makeNode(PGPathElement);
if (dash[0] == '<') { /* ArrowKleeneOptional accepts <- but that is not ok here */
parser_yyerror("PGQ cannot accept < after ] edge pattern closing.");
}
n->match_type = (dash[1] == '>')?
((left[0] == '<')?PG_MATCH_EDGE_LEFT_RIGHT:PG_MATCH_EDGE_RIGHT):
((left[0] == '<')?PG_MATCH_EDGE_LEFT:PG_MATCH_EDGE_ANY);
Expand All @@ -861,10 +807,10 @@ EdgePattern:
}
}
|
ArrowKleeneOptional
Arrow KleeneOptional
{
PGSubPath *p = (PGSubPath*) $1;
char *left = (char*) p->path;
PGSubPath *p = (PGSubPath*) $2;
char *left = (char*) $1;
PGPathElement *n = makeNode(PGPathElement);;
char *dash = left + (left[0] == '<');
n->label_expr = NULL;
Expand Down
3 changes: 1 addition & 2 deletions third_party/libpg_query/grammar/types/pgq.yh
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@
%type <node> OrLabelExpression
%type <node> LabelExpressionOptional
%type <str> Arrow
%type <str> StickyDash
%type <str> ArrowRight
%type <str> ArrowLeft
%type <node> ArrowKleeneOptional
%type <str> VariableOptional
%type <node> FullElementSpec
%type <list> EdgePattern
Expand Down
10 changes: 6 additions & 4 deletions third_party/libpg_query/scan.l
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,12 @@ other .
nchars = slashstar - yytext;
}

/* for PGQ it is confusing if + or * is glued to an arrow (<-> -> <-) or end of it (-> > -) */
char* prefix_first = yytext + (yytext[0] == '<'); /* skip: reduces prefix possibilities to (-> > -) */
char* prefix_last = yytext + nchars - (1 + (yytext[nchars-1] == '*' || yytext[nchars-1] == '+'));
if ((prefix_last == prefix_first+1 && *prefix_first == '-' && *prefix_last == '>') ||
(prefix_last == prefix_first && (*prefix_first == '-' || *prefix_first == '>'))) nchars = 1; /* break it up */

/*
* For SQL compatibility, '+' and '-' cannot be the
* last char of a multi-char operator unless the operator
Expand Down Expand Up @@ -940,10 +946,6 @@ other .
nchars = strchr(yytext, '?') - yytext;
}

if (nchars == 2 && yytext[0] == '>' && (yytext[1] == '*' || yytext[1] == '+')) {
nchars = 1; /* for PGQ it is confusing in "- >*" to glue >* into one op */
}

SET_YYLLOC();

if ((yy_size_t) nchars < yyleng)
Expand Down
Loading

0 comments on commit 7273679

Please sign in to comment.