Start implementing SELECT statements for parser

This commit is contained in:
Simon Binder 2019-06-16 21:23:33 +02:00
parent b442d32a87
commit d125a844da
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
11 changed files with 96 additions and 19 deletions

View File

@ -1,5 +1,12 @@
import 'package:sqlparser/src/ast/expressions/literals.dart';
import 'package:sqlparser/src/ast/expressions/simple.dart';
import 'package:sqlparser/src/reader/tokenizer/token.dart';
part 'clauses/limit.dart';
part 'expressions/expressions.dart';
part 'expressions/literals.dart';
part 'expressions/simple.dart';
part 'statements/select.dart';
abstract class AstNode {
Iterable<AstNode> get childNodes;
@ -7,6 +14,10 @@ abstract class AstNode {
}
abstract class AstVisitor<T> {
T visitSelectStatement(SelectStatement e);
T visitLimit(Limit e);
T visitBinaryExpression(BinaryExpression e);
T visitUnaryExpression(UnaryExpression e);
T visitIsExpression(IsExpression e);

View File

@ -0,0 +1,17 @@
part of '../ast.dart';
class Limit extends AstNode {
Expression count;
Token offsetSeparator; // can either be OFFSET or just a comma
Expression offset;
Limit({this.count, this.offsetSeparator, this.offset});
@override
T accept<T>(AstVisitor<T> visitor) {
return visitor.visitLimit(this);
}
@override
Iterable<AstNode> get childNodes => [count, if (offset != null) offset];
}

View File

@ -1,4 +1,4 @@
import 'package:sqlparser/src/ast/ast.dart';
part of '../ast.dart';
abstract class Expression implements AstNode {
const Expression();

View File

@ -1,8 +1,4 @@
import 'package:sqlparser/src/ast/ast.dart';
import 'package:sqlparser/src/reader/tokenizer/token.dart';
import 'expressions.dart';
part of '../ast.dart';
// https://www.sqlite.org/syntax/literal-value.html
abstract class Literal extends Expression {

View File

@ -1,7 +1,4 @@
import 'package:sqlparser/src/ast/ast.dart';
import 'package:sqlparser/src/reader/tokenizer/token.dart';
import 'expressions.dart';
part of '../ast.dart';
class UnaryExpression extends Expression {
final Token operator;

View File

@ -0,0 +1,16 @@
part of '../ast.dart';
class SelectStatement extends AstNode {
final Expression where;
final Limit limit;
SelectStatement({this.where, this.limit});
@override
T accept<T>(AstVisitor<T> visitor) {
return visitor.visitSelectStatement(this);
}
@override
Iterable<AstNode> get childNodes => null;
}

View File

@ -1,7 +1,5 @@
import 'package:meta/meta.dart';
import 'package:sqlparser/src/ast/expressions/expressions.dart';
import 'package:sqlparser/src/ast/expressions/literals.dart';
import 'package:sqlparser/src/ast/expressions/simple.dart';
import 'package:sqlparser/src/ast/ast.dart';
import 'package:sqlparser/src/reader/tokenizer/token.dart';
const _comparisonOperators = [
@ -72,6 +70,44 @@ class Parser {
_error(message);
}
/// Parses a [SelectStatement], or returns null if there is no select token
/// after the current position.
SelectStatement select() {
if (!_match(const [TokenType.select])) return null;
// todo parse result column
final where = _where();
final limit = _limit();
return SelectStatement(where: where, limit: limit);
}
/// Parses a where clause if there is one at the current position
Expression _where() {
if (_match(const [TokenType.where])) {
return expression();
}
return null;
}
/// Parses a [Limit] clause, or returns null if there is no limit token after
/// the current position.
Limit _limit() {
if (!_match(const [TokenType.limit])) return null;
final count = expression();
Token offsetSep;
Expression offset;
if (_match(const [TokenType.comma, TokenType.offset])) {
offsetSep = _previous;
offset = expression();
}
return Limit(count: count, offsetSeparator: offsetSep, offset: offset);
}
/* We parse expressions here.
* Operators have the following precedence:
* - + ~ NOT (unary)

View File

@ -45,9 +45,13 @@ enum TokenType {
identifier,
select,
from,
where,
limit,
offset,
eof,
}
@ -55,6 +59,8 @@ const Map<String, TokenType> keywords = {
'SELECT': TokenType.select,
'FROM': TokenType.from,
'WHERE': TokenType.where,
'LIMIT': TokenType.limit,
'OFFSET': TokenType.offset,
'IS': TokenType.$is,
'IN': TokenType.$in,
'LIKE': TokenType.like,

View File

@ -1,5 +1,4 @@
import 'package:sqlparser/src/ast/ast.dart';
import 'package:sqlparser/src/ast/expressions/simple.dart';
/// Checks whether [a] and [b] are equal. If they aren't, throws an exception.
void enforceEqual(AstNode a, AstNode b) {

View File

@ -7,7 +7,7 @@ issue_tracker: https://github.com/simolus3/moor/issues
author: Simon Binder <oss@simonbinder.eu>
environment:
sdk: '>=2.2.0 <3.0.0'
sdk: '>=2.2.2 <3.0.0'
dev_dependencies:
test: ^1.0.0

View File

@ -1,5 +1,4 @@
import 'package:sqlparser/src/ast/expressions/literals.dart';
import 'package:sqlparser/src/ast/expressions/simple.dart';
import 'package:sqlparser/src/ast/ast.dart';
import 'package:sqlparser/src/reader/parser/parser.dart';
import 'package:sqlparser/src/reader/tokenizer/scanner.dart';
import 'package:sqlparser/src/reader/tokenizer/token.dart';