Parse declared statements in moor files

This commit is contained in:
Simon Binder 2019-09-07 20:26:51 +02:00
parent 8268867369
commit 1ed1e3ba94
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
5 changed files with 76 additions and 8 deletions

View File

@ -21,6 +21,7 @@ part 'expressions/subquery.dart';
part 'expressions/tuple.dart';
part 'expressions/variables.dart';
part 'moor/declared_statement.dart';
part 'moor/import_statement.dart';
part 'schema/column_definition.dart';
@ -178,6 +179,7 @@ abstract class AstVisitor<T> {
T visitNamedVariable(ColonNamedVariable e);
T visitMoorImportStatement(ImportStatement e);
T visitMoorDeclaredStatement(DeclaredStatement e);
}
/// Visitor that walks down the entire tree, visiting all children in order.
@ -293,6 +295,9 @@ class RecursiveVisitor<T> extends AstVisitor<T> {
@override
T visitMoorImportStatement(ImportStatement e) => visitChildren(e);
@override
T visitMoorDeclaredStatement(DeclaredStatement e) => visitChildren(e);
@protected
T visitChildren(AstNode e) {
for (var child in e.childNodes) {

View File

@ -0,0 +1,25 @@
part of '../ast.dart';
/// A declared statement inside a `.moor` file. It consists of an identifier,
/// followed by a colon and the query to run.
class DeclaredStatement extends Statement {
final String name;
final CrudStatement statement;
IdentifierToken identifier;
Token colon;
DeclaredStatement(this.name, this.statement);
@override
T accept<T>(AstVisitor<T> visitor) =>
visitor.visitMoorDeclaredStatement(this);
@override
Iterable<AstNode> get childNodes => [statement];
@override
bool contentEquals(DeclaredStatement other) {
return other.name == name;
}
}

View File

@ -1,5 +1,6 @@
part of '../ast.dart';
/// An `import "file.dart";` statement that can appear inside a moor file.
class ImportStatement extends Statement {
Token importToken;
StringLiteralToken importString;

View File

@ -157,14 +157,11 @@ class Parser extends ParserBase
Statement statement({bool expectEnd = true}) {
final first = _peek;
var stmt = select() ??
_deleteStmt() ??
_update() ??
_insertStmt() ??
_createTable();
Statement stmt = _crud();
stmt ??= _createTable();
if (enableMoorExtensions) {
stmt ??= _import();
stmt ??= _import() ?? _declaredStatement();
}
if (stmt == null) {
@ -181,6 +178,17 @@ class Parser extends ParserBase
return stmt..setSpan(first, _previous);
}
CrudStatement _crud() {
// writing select() ?? _deleteStmt() and so on doesn't cast to CrudStatement
// for some reason.
CrudStatement stmt = select();
stmt ??= _deleteStmt();
stmt ??= _update();
stmt ??= _insertStmt();
return stmt;
}
ImportStatement _import() {
if (_matchOne(TokenType.import)) {
final importToken = _previous;
@ -195,6 +203,23 @@ class Parser extends ParserBase
return null;
}
DeclaredStatement _declaredStatement() {
if (_check(TokenType.identifier) || _peek is KeywordToken) {
final name = _consumeIdentifier('Expected a name for a declared query',
lenient: true);
final colon =
_consume(TokenType.colon, 'Expected colon (:) followed by a query');
final stmt = _crud();
return DeclaredStatement(name.identifier, stmt)
..identifier = name
..colon = colon;
}
return null;
}
List<Statement> statements() {
final stmts = <Statement>[];
while (!_isAtEnd) {

View File

@ -46,10 +46,10 @@ void main() {
);
});
test('parses import directives in moor mode', () {
test('parses imports and declared statements in moor mode', () {
final sql = r'''
import 'test.dart';
SELECT * FROM tbl;
query: SELECT * FROM tbl;
''';
final tokens = Scanner(sql, scanMoorTokens: true).scanTokens();
@ -62,5 +62,17 @@ void main() {
expect(parsedImport.importToken, tokens[0]);
expect(parsedImport.importString, tokens[1]);
expect(parsedImport.semicolon, tokens[2]);
final declared = statements[1] as DeclaredStatement;
enforceEqual(
declared,
DeclaredStatement(
'query',
SelectStatement(
columns: [StarResultColumn(null)],
from: [TableReference('tbl', null)],
),
),
);
});
}