| Index: packages/polymer_expressions/lib/parser.dart
|
| diff --git a/packages/polymer_expressions/lib/parser.dart b/packages/polymer_expressions/lib/parser.dart
|
| deleted file mode 100644
|
| index 7ab9b4c38dfb05b744735cb8c8b2c841eb10fa86..0000000000000000000000000000000000000000
|
| --- a/packages/polymer_expressions/lib/parser.dart
|
| +++ /dev/null
|
| @@ -1,324 +0,0 @@
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library polymer_expressions.parser;
|
| -
|
| -import 'tokenizer.dart';
|
| -export 'tokenizer.dart' show ParseException;
|
| -import 'expression.dart';
|
| -
|
| -const _UNARY_OPERATORS = const <String>['+', '-', '!'];
|
| -const _BINARY_OPERATORS = const <String>['+', '-', '*', '/', '%', '^', '==',
|
| - '!=', '>', '<', '>=', '<=', '||', '&&', '&', '===', '!==', '|'];
|
| -
|
| -Expression parse(String expr) => new Parser(expr).parse();
|
| -
|
| -class Parser {
|
| - final AstFactory _astFactory;
|
| - final Tokenizer _tokenizer;
|
| - List<Token> _tokens;
|
| - Iterator _iterator;
|
| - Token get _token => _iterator.current;
|
| -
|
| - Parser(String input, {AstFactory astFactory})
|
| - : _tokenizer = new Tokenizer(input),
|
| - _astFactory = (astFactory == null) ? new AstFactory() : astFactory;
|
| -
|
| - Expression parse() {
|
| - _tokens = _tokenizer.tokenize();
|
| - _iterator = _tokens.iterator;
|
| - _advance();
|
| - return _parseExpression();
|
| - }
|
| -
|
| - _advance([int kind, String value]) {
|
| - if ((kind != null && (_token == null || _token.kind != kind))
|
| - || (value != null && (_token == null || _token.value != value))) {
|
| - throw new ParseException("Expected kind $kind ($value): $_token");
|
| - }
|
| - _iterator.moveNext();
|
| - }
|
| -
|
| - Expression _parseExpression() {
|
| - if (_token == null) return _astFactory.empty();
|
| - var expr = _parseUnary();
|
| - return (expr == null) ? null : _parsePrecedence(expr, 0);
|
| - }
|
| -
|
| - // _parsePrecedence and _parseBinary implement the precedence climbing
|
| - // algorithm as described in:
|
| - // http://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method
|
| - Expression _parsePrecedence(Expression left, int precedence) {
|
| - assert(left != null);
|
| - while (_token != null) {
|
| - if (_token.kind == GROUPER_TOKEN) {
|
| - if (_token.value == '(') {
|
| - var args = _parseArguments();
|
| - assert(args != null);
|
| - left = _astFactory.invoke(left, null, args);
|
| - } else if (_token.value == '[') {
|
| - var indexExpr = _parseIndex();
|
| - left = _astFactory.index(left, indexExpr);
|
| - } else {
|
| - break;
|
| - }
|
| - } else if (_token.kind == DOT_TOKEN) {
|
| - _advance();
|
| - var right = _parseUnary();
|
| - left = _makeInvokeOrGetter(left, right);
|
| - } else if (_token.kind == KEYWORD_TOKEN) {
|
| - if (_token.value == 'in') {
|
| - left = _parseInExpression(left);
|
| - } else if (_token.value == 'as') {
|
| - left = _parseAsExpression(left);
|
| - } else {
|
| - break;
|
| - }
|
| - } else if (_token.kind == OPERATOR_TOKEN
|
| - && _token.precedence >= precedence) {
|
| - left = _token.value == '?' ? _parseTernary(left) : _parseBinary(left);
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - return left;
|
| - }
|
| -
|
| - // invoke or getter
|
| - Expression _makeInvokeOrGetter(left, right) {
|
| - if (right is Identifier) {
|
| - return _astFactory.getter(left, right.value);
|
| - } else if (right is Invoke && right.receiver is Identifier) {
|
| - Identifier method = right.receiver;
|
| - return _astFactory.invoke(left, method.value, right.arguments);
|
| - } else {
|
| - throw new ParseException("expected identifier: $right");
|
| - }
|
| - }
|
| -
|
| - Expression _parseBinary(left) {
|
| - var op = _token;
|
| - if (!_BINARY_OPERATORS.contains(op.value)) {
|
| - throw new ParseException("unknown operator: ${op.value}");
|
| - }
|
| - _advance();
|
| - var right = _parseUnary();
|
| - while (_token != null
|
| - && (_token.kind == OPERATOR_TOKEN
|
| - || _token.kind == DOT_TOKEN
|
| - || _token.kind == GROUPER_TOKEN)
|
| - && _token.precedence > op.precedence) {
|
| - right = _parsePrecedence(right, _token.precedence);
|
| - }
|
| - return _astFactory.binary(left, op.value, right);
|
| - }
|
| -
|
| - Expression _parseUnary() {
|
| - if (_token.kind == OPERATOR_TOKEN) {
|
| - var value = _token.value;
|
| - if (value == '+' || value == '-') {
|
| - _advance();
|
| - if (_token.kind == INTEGER_TOKEN) {
|
| - return _parseInteger(value);
|
| - } else if (_token.kind == DECIMAL_TOKEN) {
|
| - return _parseDecimal(value);
|
| - } else {
|
| - var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE);
|
| - return _astFactory.unary(value, expr);
|
| - }
|
| - } else if (value == '!') {
|
| - _advance();
|
| - var expr = _parsePrecedence(_parsePrimary(), POSTFIX_PRECEDENCE);
|
| - return _astFactory.unary(value, expr);
|
| - } else {
|
| - throw new ParseException("unexpected token: $value");
|
| - }
|
| - }
|
| - return _parsePrimary();
|
| - }
|
| -
|
| - Expression _parseTernary(condition) {
|
| - _advance(OPERATOR_TOKEN, '?');
|
| - var trueExpr = _parseExpression();
|
| - _advance(COLON_TOKEN);
|
| - var falseExpr = _parseExpression();
|
| - return _astFactory.ternary(condition, trueExpr, falseExpr);
|
| - }
|
| -
|
| - Expression _parsePrimary() {
|
| - var kind = _token.kind;
|
| - switch (kind) {
|
| - case KEYWORD_TOKEN:
|
| - var keyword = _token.value;
|
| - if (keyword == 'this') {
|
| - _advance();
|
| - // TODO(justin): return keyword node
|
| - return _astFactory.identifier('this');
|
| - } else if (KEYWORDS.contains(keyword)) {
|
| - throw new ParseException('unexpected keyword: $keyword');
|
| - }
|
| - throw new ParseException('unrecognized keyword: $keyword');
|
| - case IDENTIFIER_TOKEN:
|
| - return _parseInvokeOrIdentifier();
|
| - case STRING_TOKEN:
|
| - return _parseString();
|
| - case INTEGER_TOKEN:
|
| - return _parseInteger();
|
| - case DECIMAL_TOKEN:
|
| - return _parseDecimal();
|
| - case GROUPER_TOKEN:
|
| - if (_token.value == '(') {
|
| - return _parseParenthesized();
|
| - } else if (_token.value == '{') {
|
| - return _parseMapLiteral();
|
| - } else if (_token.value == '[') {
|
| - return _parseListLiteral();
|
| - }
|
| - return null;
|
| - case COLON_TOKEN:
|
| - throw new ParseException('unexpected token ":"');
|
| - default:
|
| - return null;
|
| - }
|
| - }
|
| -
|
| - ListLiteral _parseListLiteral() {
|
| - var items = [];
|
| - do {
|
| - _advance();
|
| - if (_token.kind == GROUPER_TOKEN && _token.value == ']') {
|
| - break;
|
| - }
|
| - items.add(_parseExpression());
|
| - } while(_token != null && _token.value == ',');
|
| - _advance(GROUPER_TOKEN, ']');
|
| - return new ListLiteral(items);
|
| - }
|
| -
|
| - MapLiteral _parseMapLiteral() {
|
| - var entries = [];
|
| - do {
|
| - _advance();
|
| - if (_token.kind == GROUPER_TOKEN && _token.value == '}') {
|
| - break;
|
| - }
|
| - entries.add(_parseMapLiteralEntry());
|
| - } while(_token != null && _token.value == ',');
|
| - _advance(GROUPER_TOKEN, '}');
|
| - return new MapLiteral(entries);
|
| - }
|
| -
|
| - MapLiteralEntry _parseMapLiteralEntry() {
|
| - var key = _parseString();
|
| - _advance(COLON_TOKEN, ':');
|
| - var value = _parseExpression();
|
| - return _astFactory.mapLiteralEntry(key, value);
|
| - }
|
| -
|
| - InExpression _parseInExpression(Expression left) {
|
| - assert(_token.value == 'in');
|
| - if (left is! Identifier) {
|
| - throw new ParseException(
|
| - "in... statements must start with an identifier");
|
| - }
|
| - _advance();
|
| - var right = _parseExpression();
|
| - return _astFactory.inExpr(left, right);
|
| - }
|
| -
|
| - AsExpression _parseAsExpression(Expression left) {
|
| - assert(_token.value == 'as');
|
| - _advance();
|
| - var right = _parseExpression();
|
| - if (right is! Identifier) {
|
| - throw new ParseException(
|
| - "'as' statements must end with an identifier");
|
| - }
|
| - return _astFactory.asExpr(left, right);
|
| - }
|
| -
|
| - Expression _parseInvokeOrIdentifier() {
|
| - if (_token.value == 'true') {
|
| - _advance();
|
| - return _astFactory.literal(true);
|
| - }
|
| - if (_token.value == 'false') {
|
| - _advance();
|
| - return _astFactory.literal(false);
|
| - }
|
| - if (_token.value == 'null') {
|
| - _advance();
|
| - return _astFactory.literal(null);
|
| - }
|
| - var identifier = _parseIdentifier();
|
| - var args = _parseArguments();
|
| - if (args == null) {
|
| - return identifier;
|
| - } else {
|
| - return _astFactory.invoke(identifier, null, args);
|
| - }
|
| - }
|
| -
|
| - Identifier _parseIdentifier() {
|
| - if (_token.kind != IDENTIFIER_TOKEN) {
|
| - throw new ParseException("expected identifier: $_token.value");
|
| - }
|
| - var value = _token.value;
|
| - _advance();
|
| - return _astFactory.identifier(value);
|
| - }
|
| -
|
| - List<Expression> _parseArguments() {
|
| - if (_token != null && _token.kind == GROUPER_TOKEN && _token.value == '(') {
|
| - var args = [];
|
| - do {
|
| - _advance();
|
| - if (_token.kind == GROUPER_TOKEN && _token.value == ')') {
|
| - break;
|
| - }
|
| - var expr = _parseExpression();
|
| - args.add(expr);
|
| - } while(_token != null && _token.value == ',');
|
| - _advance(GROUPER_TOKEN, ')');
|
| - return args;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - Expression _parseIndex() {
|
| - if (_token != null && _token.kind == GROUPER_TOKEN && _token.value == '[') {
|
| - _advance();
|
| - var expr = _parseExpression();
|
| - _advance(GROUPER_TOKEN, ']');
|
| - return expr;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - ParenthesizedExpression _parseParenthesized() {
|
| - _advance();
|
| - var expr = _parseExpression();
|
| - _advance(GROUPER_TOKEN, ')');
|
| - return _astFactory.parenthesized(expr);
|
| - }
|
| -
|
| - Literal<String> _parseString() {
|
| - var value = _astFactory.literal(_token.value);
|
| - _advance();
|
| - return value;
|
| - }
|
| -
|
| - Literal<int> _parseInteger([String prefix = '']) {
|
| - var value = _astFactory.literal(int.parse('$prefix${_token.value}'));
|
| - _advance();
|
| - return value;
|
| - }
|
| -
|
| - Literal<double> _parseDecimal([String prefix = '']) {
|
| - var value = _astFactory.literal(double.parse('$prefix${_token.value}'));
|
| - _advance();
|
| - return value;
|
| - }
|
| -
|
| -}
|
|
|