[GRASS5] PATCH: sql expression parser
Glynn Clements
glynn at gclements.plus.com
Wed Jun 15 08:04:30 EDT 2005
Daniel Calvelo Aros wrote:
> > The SQL interpreter in the DBF driver doesn't have a negation
> > operator.
> >
> > I thought about parsing -E as a subtraction (0 - E), although I'm not
> > sure whether there's something I'm overlooking.
>
> I'd rather use (-1)*E, which is also within the grammar, and I *think* works
> better wrt precedence rules and allows a*-b. I might be overlooking stg also.
Using (0 - E) will work just as well in that regard. I was initially
concerned about how to handle int-vs-float, but I've since confirmed
that the interpreter expands types:
(int - int) => int
(int - float) => float
so subtracting the expression from integer zero should do the right
thing.
> What does e.g. octave do? BTW I'd use yacc's %prec, but that's just laziness
> of course.
It isn't parsing that's the issue, but what to insert into the parse
tree once a negation has been recognised.
The attached patch inserts a y_term type between y_product and y_atom,
with the definition:
y_term:
y_atom { $$ = $1; }
| '-' y_term {
$$ = sqpNewExpressionNode ( sqpOperatorCode("-"), sqpNewValueNode ( NULL, 0, 0.0, SQLP_I ), $2 );
}
;
This allows for negations to be negated, i.e. --E is interpreted as
-(-E). If this is not desired (I have no idea what the standard says
about this), then the line:
| '-' y_term {
would need to be changed to:
| '-' y_atom {
--
Glynn Clements <glynn at gclements.plus.com>
-------------- next part --------------
Index: lib/db/sqlp/lex.l
===================================================================
RCS file: /grassrepository/grass51/lib/db/sqlp/lex.l,v
retrieving revision 1.19
diff -u -r1.19 lex.l
--- lib/db/sqlp/lex.l 9 Sep 2004 20:02:23 -0000 1.19
+++ lib/db/sqlp/lex.l 15 Jun 2005 11:57:28 -0000
@@ -82,18 +82,6 @@
}
/***************************************
- * ARITHMETICAL OPERATOR
- * Conflict of * as operator with * as all columns, what to do?
- ***************************************/
-
-"+" |
-"-" |
-"/" {
- yylval.strval = (char*)strdup(yytext);
- return ARITHMETICAL_OPERATOR;
- }
-
- /***************************************
* COMPARISON OPERATOR
***************************************/
Index: lib/db/sqlp/yac.y
===================================================================
RCS file: /grassrepository/grass51/lib/db/sqlp/yac.y,v
retrieving revision 1.20
diff -u -r1.20 yac.y
--- lib/db/sqlp/yac.y 9 Sep 2004 20:02:23 -0000 1.20
+++ lib/db/sqlp/yac.y 15 Jun 2005 11:57:28 -0000
@@ -41,13 +41,17 @@
/* operators */
%type <node> y_column
%type <node> y_value
+%type <node> y_atom
+%type <node> y_term
+%type <node> y_product
%type <node> y_expression
%type <node> y_comparison
-%type <node> y_condition
+%type <node> y_boolean
+%type <node> y_sub_condition2
%type <node> y_sub_condition
+%type <node> y_condition
/* literal keyword tokens */
-%token <strval> ARITHMETICAL_OPERATOR
%token <strval> COMPARISON_OPERATOR
%token <strval> NAME
%token <strval> STRING
@@ -194,13 +198,20 @@
;
y_sub_condition:
- y_comparison { $$ = $1; }
- | '(' y_sub_condition ')' { $$ = $2; }
- | y_sub_condition AND y_sub_condition { $$ = sqpNewExpressionNode (SQLP_AND, $1, $3); }
- | y_sub_condition OR y_sub_condition { $$ = sqpNewExpressionNode (SQLP_OR, $1, $3); }
- | NOT y_sub_condition { $$ = sqpNewExpressionNode ( SQLP_NOT, NULL, $2); }
+ y_sub_condition2 { $$ = $1; }
+ | y_sub_condition OR y_sub_condition2 { $$ = sqpNewExpressionNode (SQLP_OR, $1, $3); }
+ ;
+
+y_sub_condition2:
+ y_boolean { $$ = $1; }
+ | y_sub_condition2 AND y_boolean { $$ = sqpNewExpressionNode (SQLP_AND, $1, $3); }
;
+y_boolean:
+ y_comparison { $$ = $1; }
+ | '(' y_sub_condition ')' { $$ = $2; }
+ | NOT y_boolean { $$ = sqpNewExpressionNode ( SQLP_NOT, NULL, $2); }
+ ;
/* Note EQUAL should be one of COMPARISON but there is maybe some reason ... */
y_comparison:
@@ -220,14 +231,36 @@
/* Mathematical expression */
y_expression:
- y_value { $$ = $1; }
- | y_column { $$ = $1; }
- | y_expression ARITHMETICAL_OPERATOR y_expression {
- $$ = sqpNewExpressionNode ( sqpOperatorCode($2), $1, $3 );
+ y_product { $$ = $1; }
+ | y_expression '+' y_product {
+ $$ = sqpNewExpressionNode ( sqpOperatorCode("+"), $1, $3 );
+ }
+ | y_expression '-' y_product {
+ $$ = sqpNewExpressionNode ( sqpOperatorCode("-"), $1, $3 );
}
- | y_expression '*' y_expression {
+ ;
+
+y_product:
+ y_term { $$ = $1; }
+ | y_product '*' y_term {
$$ = sqpNewExpressionNode ( sqpOperatorCode("*"), $1, $3 );
}
+ | y_product '/' y_term {
+ $$ = sqpNewExpressionNode ( sqpOperatorCode("/"), $1, $3 );
+ }
+ ;
+
+y_term:
+ y_atom { $$ = $1; }
+ | '-' y_term {
+ $$ = sqpNewExpressionNode ( sqpOperatorCode("-"), sqpNewValueNode ( NULL, 0, 0.0, SQLP_I ), $2 );
+ }
+ ;
+
+y_atom:
+ y_value { $$ = $1; }
+ | y_column { $$ = $1; }
+ | '(' y_expression ')' { $$ = $2; }
;
/* Value used in expressions */
More information about the grass-dev
mailing list