mirror of https://github.com/AMT-Cheif/drift.git
Parse function expressions
This commit is contained in:
parent
1c75c9d3e8
commit
8bbf6d8054
|
@ -9,6 +9,7 @@ part 'common/queryables.dart';
|
|||
part 'common/renamable.dart';
|
||||
|
||||
part 'expressions/expressions.dart';
|
||||
part 'expressions/function.dart';
|
||||
part 'expressions/literals.dart';
|
||||
part 'expressions/reference.dart';
|
||||
part 'expressions/simple.dart';
|
||||
|
@ -41,6 +42,7 @@ abstract class AstVisitor<T> {
|
|||
T visitIsExpression(IsExpression e);
|
||||
T visitLiteral(Literal e);
|
||||
T visitReference(Reference e);
|
||||
T visitFunction(FunctionExpression e);
|
||||
|
||||
T visitNumberedVariable(NumberedVariable e);
|
||||
T visitNamedVariable(ColonNamedVariable e);
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
part of '../ast.dart';
|
||||
|
||||
class FunctionExpression extends Expression {
|
||||
final String name;
|
||||
final FunctionParameters parameters;
|
||||
|
||||
FunctionExpression({@required this.name, @required this.parameters});
|
||||
|
||||
@override
|
||||
T accept<T>(AstVisitor<T> visitor) => visitor.visitFunction(this);
|
||||
|
||||
@override
|
||||
Iterable<AstNode> get childNodes {
|
||||
return [
|
||||
if (parameters is ExprFunctionParameters)
|
||||
...(parameters as ExprFunctionParameters).parameters
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
bool contentEquals(FunctionExpression other) {
|
||||
if (other.name != name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parameters is StarFunctionParameter) {
|
||||
return other.parameters is StarFunctionParameter;
|
||||
} else if (parameters is ExprFunctionParameters) {
|
||||
final typedParams = parameters as ExprFunctionParameters;
|
||||
final typedOther = other.parameters as ExprFunctionParameters;
|
||||
return typedParams.equals(typedOther);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker interface for anything that can be inside the parentheses after a
|
||||
/// function name.
|
||||
abstract class FunctionParameters {}
|
||||
|
||||
/// Using a star as a function parameter. For instance: "COUNT(*)".
|
||||
class StarFunctionParameter implements FunctionParameters {
|
||||
const StarFunctionParameter();
|
||||
}
|
||||
|
||||
class ExprFunctionParameters implements FunctionParameters {
|
||||
final bool distinct;
|
||||
final List<Expression> parameters;
|
||||
|
||||
ExprFunctionParameters({this.parameters = const [], this.distinct = false});
|
||||
|
||||
bool equals(ExprFunctionParameters other) {
|
||||
return other.distinct == distinct && other.parameters == parameters;
|
||||
}
|
||||
}
|
|
@ -483,13 +483,21 @@ class Parser {
|
|||
_consume(TokenType.rightParen, 'Expected a closing bracket');
|
||||
return Parentheses(left, expr, _previous);
|
||||
case TokenType.identifier:
|
||||
// could be table.column, function(...) or just column
|
||||
final first = _previous as IdentifierToken;
|
||||
if (_match(const [TokenType.dot])) {
|
||||
|
||||
if (_matchOne(TokenType.dot)) {
|
||||
final second =
|
||||
_consume(TokenType.identifier, 'Expected a column name here')
|
||||
as IdentifierToken;
|
||||
return Reference(
|
||||
tableName: first.identifier, columnName: second.identifier);
|
||||
} else if (_matchOne(TokenType.leftParen)) {
|
||||
final parameters = _functionParameters();
|
||||
_consume(TokenType.rightParen,
|
||||
'Expected closing bracket after argument list');
|
||||
return FunctionExpression(
|
||||
name: first.identifier, parameters: parameters);
|
||||
} else {
|
||||
return Reference(columnName: first.identifier);
|
||||
}
|
||||
|
@ -507,7 +515,6 @@ class Parser {
|
|||
final identifier = _consume(TokenType.identifier,
|
||||
'Expected an identifier for the named variable') as IdentifierToken;
|
||||
final content = identifier.identifier;
|
||||
|
||||
return ColonNamedVariable(':$content');
|
||||
default:
|
||||
break;
|
||||
|
@ -516,4 +523,17 @@ class Parser {
|
|||
// nothing found -> issue error
|
||||
_error('Could not parse this expression');
|
||||
}
|
||||
|
||||
FunctionParameters _functionParameters() {
|
||||
if (_matchOne(TokenType.star)) {
|
||||
return const StarFunctionParameter();
|
||||
}
|
||||
|
||||
final distinct = _matchOne(TokenType.distinct);
|
||||
final parameters = <Expression>[];
|
||||
while (_peek.type != TokenType.rightParen) {
|
||||
parameters.add(expression());
|
||||
}
|
||||
return ExprFunctionParameters(distinct: distinct, parameters: parameters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import 'utils.dart';
|
|||
|
||||
void main() {
|
||||
test('parses simple expressions', () {
|
||||
final scanner = Scanner('3 * 4 + 5 == 17');
|
||||
final scanner = Scanner('3 * 4 + 5 == COUNT(*)');
|
||||
final tokens = scanner.scanTokens();
|
||||
final parser = Parser(tokens);
|
||||
|
||||
|
@ -27,7 +27,10 @@ void main() {
|
|||
NumericLiteral(5, token(TokenType.numberLiteral)),
|
||||
),
|
||||
token(TokenType.doubleEqual),
|
||||
NumericLiteral(17, token(TokenType.numberLiteral)),
|
||||
FunctionExpression(
|
||||
name: 'COUNT',
|
||||
parameters: const StarFunctionParameter(),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue