platform/lib/src/language/parser.dart

188 lines
5.1 KiB
Dart
Raw Normal View History

2017-02-05 23:08:03 +00:00
library graphql_parser.language.parser;
2017-01-22 23:15:53 +00:00
import 'ast/ast.dart';
2017-01-25 04:28:09 +00:00
import 'syntax_error.dart';
2017-01-22 23:15:53 +00:00
import 'token.dart';
2017-01-25 04:28:09 +00:00
import 'token_type.dart';
2017-01-22 23:15:53 +00:00
2017-07-03 15:37:35 +00:00
class Parser {
Token _current;
2017-01-25 04:28:09 +00:00
final List<SyntaxError> _errors = [];
2017-07-03 15:37:35 +00:00
int _index = -1;
2017-01-22 23:15:53 +00:00
2017-07-03 15:37:35 +00:00
final List<Token> tokens;
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
Parser(this.tokens);
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
Token get current => _current;
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
List<SyntaxError> get errors => new List<SyntaxError>.unmodifiable(_errors);
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
bool next(TokenType type) {
if (peek()?.type == type) {
_current = tokens[++_index];
return true;
}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
return false;
2017-01-22 23:15:53 +00:00
}
2017-07-03 15:37:35 +00:00
Token peek() {
if (_index < tokens.length - 1) {
return tokens[_index + 1];
}
return null;
2017-01-25 04:28:09 +00:00
}
2017-07-03 15:37:35 +00:00
DocumentContext parseDocument() {}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
FragmentDefinitionContext parseFragmentDefinition() {}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
FragmentSpreadContext parseFragmentSpread() {}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
InlineFragmentContext parseInlineFragment() {}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
SelectionSetContext parseSelectionSet() {}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
SelectionContext parseSelection() {}
2017-01-25 04:28:09 +00:00
2017-07-03 15:37:35 +00:00
FieldContext parseField() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
FieldNameContext parseFieldName() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
AliasContext parseAlias() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
VariableDefinitionsContext parseVariableDefinitions() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
VariableDefinitionContext parseVariableDefinition() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
List<DirectiveContext> parseDirectives() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
DirectiveContext parseDirective() {
if (next(TokenType.ARROBA)) {
var ARROBA = current;
if (next(TokenType.NAME)) {
var NAME = current;
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
if (next(TokenType.COLON)) {
var COLON = current;
var val = parseValueOrVariable();
if (val != null)
return new DirectiveContext(
ARROBA, NAME, COLON, null, null, null, val);
else
throw new SyntaxError.fromSourceLocation(
'Expected value or variable in directive after colon.',
COLON.span.end);
} else if (next(TokenType.LPAREN)) {
var LPAREN = current;
var arg = parseArgument();
if (arg != null) {
if (next(TokenType.RPAREN)) {
return new DirectiveContext(
ARROBA, NAME, null, LPAREN, current, arg, null);
} else
throw new SyntaxError.fromSourceLocation(
'Expected \'(\'', arg.valueOrVariable.span.end);
} else
throw new SyntaxError.fromSourceLocation(
'Expected argument in directive.', LPAREN.span.end);
} else
return new DirectiveContext(
ARROBA, NAME, null, null, null, null, null);
} else
throw new SyntaxError.fromSourceLocation(
'Expected name for directive.', ARROBA.span.end);
} else
return null;
}
ArgumentContext parseArgument() {
if (next(TokenType.NAME)) {
var NAME = current;
if (next(TokenType.COLON)) {
var COLON = current;
var val = parseValueOrVariable();
if (val != null)
return new ArgumentContext(NAME, COLON, val);
else
throw new SyntaxError.fromSourceLocation(
'Expected value or variable in argument.', COLON.span.end);
} else
throw new SyntaxError.fromSourceLocation(
'Expected colon after name in argument.', NAME.span.end);
} else
return null;
2017-01-25 04:28:09 +00:00
}
2017-07-03 15:37:35 +00:00
ValueOrVariableContext parseValueOrVariable() {
var value = parseValue();
if (value != null)
return new ValueOrVariableContext(value, null);
else {
var variable = parseVariable();
if (variable != null)
return new ValueOrVariableContext(null, variable);
else
return null;
2017-02-05 23:08:03 +00:00
}
2017-07-03 15:37:35 +00:00
}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
VariableContext parseVariable() {
if (next(TokenType.DOLLAR)) {
var DOLLAR = current;
if (next(TokenType.NAME))
return new VariableContext(DOLLAR, current);
else
throw new SyntaxError.fromSourceLocation(
'Expected name for variable; found a lone "\$" instead.',
DOLLAR.span.end);
} else
return null;
2017-02-05 23:08:03 +00:00
}
2017-07-03 15:37:35 +00:00
DefaultValueContext parseDefaultValue() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
TypeConditionContext parseTypeCondition() {}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
ValueContext parseValue() {
return parseStringValue() ??
parseNumberValue() ??
parseBooleanValue() ??
parseArrayValue();
}
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
StringValueContext parseStringValue() =>
next(TokenType.STRING) ? new StringValueContext(current) : null;
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
NumberValueContext parseNumberValue() =>
next(TokenType.NUMBER) ? new NumberValueContext(current) : null;
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
BooleanValueContext parseBooleanValue() =>
next(TokenType.BOOLEAN) ? new BooleanValueContext(current) : null;
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
ArrayValueContext parseArrayValue() {
if (next(TokenType.LBRACKET)) {
var LBRACKET = current;
List<ValueContext> values = [];
ValueContext value = parseValue();
2017-02-05 23:08:03 +00:00
2017-07-03 15:37:35 +00:00
while (value != null) {
values.add(value);
if (next(TokenType.COMMA)) {
value = parseValue();
} else
break;
}
2017-01-22 23:15:53 +00:00
2017-07-03 15:37:35 +00:00
if (next(TokenType.RBRACKET)) {
return new ArrayValueContext(LBRACKET, current)..values.addAll(values);
} else
throw new SyntaxError.fromSourceLocation(
'Unterminated array literal.', LBRACKET.span.end);
} else
return null;
2017-01-22 23:15:53 +00:00
}
}