diff --git a/docs/docs/design/miniob-sql-expression.md b/docs/docs/design/miniob-sql-expression.md index 23d05c258..6f1e4778f 100644 --- a/docs/docs/design/miniob-sql-expression.md +++ b/docs/docs/design/miniob-sql-expression.md @@ -116,13 +116,13 @@ expression 的规则会比较简单,加减乘除,以及负号取反。这里 %left '*' '/' ``` -%left 表示左结合,就是遇到指定的符号,先跟左边的符号结合。而定义的顺序就是优先级的顺序,越靠后的优先级越高。 +%left 表示左结合,就是遇到指定的符号,先跟左边的符号结合,比如 `1+2+3` 会被解析为 `(1+2)+3`。而定义的顺序就是优先级的顺序,越靠后的优先级越高。 负号运算符的特殊性除了它的优先级,还有它的结合性。普通的运算,比如 `1+2`,是两个数字即两个表达式,一个运算符。而负号的表示形式是 `-(1+2)`,即一个符号,一个表达式。 ```yacc -%nonassoc UMINUS +%right UMINUS ``` -表示 `UMINUS` 是一个一元运算符,没有结合性。在.y中,放到了 `%left '*' '/'` 的后面,说明优先级比乘除运算符高。 +表示 `UMINUS` 是一个一元运算符,%right 表示右结合,作用与左结合类似,保证 `- -5` 等类似表达式可以被正确识别为 `-(-5)`。在.y中,放到了 `%left '*' '/'` 的后面,说明优先级比乘除运算符高。 expression 的规则如下: ```yacc @@ -161,12 +161,4 @@ expression '+' expression { ## 抽象表达式类型 上面语法分析中描述的都是算术表达式,但是真实的SQL语句中,像字段名、常量、比较运算、函数、子查询等都是表达式。我们需要定义一个基类,然后派生出各种表达式类型。 -这些表达式的定义已经在expression.h中定义,但是没有在语法解析中体现。更完善的做法是在 select 的属性列表、where 条件、insert 的 values等语句中,都使用表达式来表示。 - -## '-' 缺陷 -由于在词法分析中,负号'-'与数字放在一起时,会被认为是一个负值数字,作为一个完整的token返回给语法分析,所以当前的语法分析无法正确的解析下面的表达式: -``` -1 -2; -``` -这个表达式的结果应该是 -1,但是当前的语法分析会认为是两个表达式,一个是1,一个是-2,这样就无法正确的计算出结果。 -当前修复此问题的成本较高,需要修改词法分析的规则,所以暂时不做处理。 \ No newline at end of file +这些表达式的定义已经在expression.h中定义,但是没有在语法解析中体现。更完善的做法是在 select 的属性列表、where 条件、insert 的 values等语句中,都使用表达式来表示。 \ No newline at end of file diff --git a/src/observer/sql/parser/lex_sql.l b/src/observer/sql/parser/lex_sql.l index fecff9b5f..2b9258ba8 100644 --- a/src/observer/sql/parser/lex_sql.l +++ b/src/observer/sql/parser/lex_sql.l @@ -78,8 +78,8 @@ QUOTE [\'\"] {WHITE_SPACE} // ignore whitespace \n ; -[\-]?{DIGIT}+ yylval->number=atoi(yytext); RETURN_TOKEN(NUMBER); -[\-]?{DIGIT}+{DOT}{DIGIT}+ yylval->floats=(float)(atof(yytext)); RETURN_TOKEN(FLOAT); +{DIGIT}+ yylval->number=atoi(yytext); RETURN_TOKEN(NUMBER); +{DIGIT}+{DOT}{DIGIT}+ yylval->floats=(float)(atof(yytext)); RETURN_TOKEN(FLOAT); ";" RETURN_TOKEN(SEMICOLON); {DOT} RETURN_TOKEN(DOT); diff --git a/src/observer/sql/parser/yacc_sql.y b/src/observer/sql/parser/yacc_sql.y index 3eeaa4520..83a909bb3 100644 --- a/src/observer/sql/parser/yacc_sql.y +++ b/src/observer/sql/parser/yacc_sql.y @@ -189,7 +189,7 @@ UnboundAggregateExpr *create_aggregate_expression(const char *aggregate_name, %left '+' '-' %left '*' '/' -%nonassoc UMINUS +%right UMINUS %% commands: command_wrapper opt_semicolon //commands or sqls. parser starts here.