LCOV - code coverage report
Current view: top level - boolean_selector-1.0.2/lib/src - scanner.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 0 38 0.0 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
       2             : // for details. All rights reserved. Use of this source code is governed by a
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import 'package:string_scanner/string_scanner.dart';
       6             : 
       7             : import 'token.dart';
       8             : 
       9             : /// A regular expression matching both whitespace and single-line comments.
      10             : ///
      11             : /// This will only match if consumes at least one character.
      12             : final _whitespaceAndSingleLineComments =
      13             :     new RegExp(r"([ \t\n]+|//[^\n]*(\n|$))+");
      14             : 
      15             : /// A regular expression matching the body of a multi-line comment, after `/*`
      16             : /// but before `*/` or a nested `/*`.
      17             : ///
      18             : /// This will only match if it consumes at least one character.
      19             : final _multiLineCommentBody = new RegExp(r"([^/*]|/[^*]|\*[^/])+");
      20             : 
      21             : /// A regular expression matching a hyphenated identifier.
      22             : ///
      23             : /// This is like a standard Dart identifier, except that it can also contain
      24             : /// hyphens.
      25             : final _hyphenatedIdentifier = new RegExp(r"[a-zA-Z_-][a-zA-Z0-9_-]*");
      26             : 
      27             : /// A scanner that converts a boolean selector string into a stream of tokens.
      28             : class Scanner {
      29             :   /// The underlying string scanner.
      30             :   final SpanScanner _scanner;
      31             : 
      32             :   /// The next token to emit.
      33             :   Token _next;
      34             : 
      35             :   /// Whether the scanner has emitted a [TokenType.endOfFile] token.
      36             :   bool _endOfFileEmitted = false;
      37             : 
      38             :   Scanner(String selector)
      39           0 :       : _scanner = new SpanScanner(selector);
      40             : 
      41             :   /// Returns the next token that will be returned by [next].
      42             :   ///
      43             :   /// Throws a [StateError] if a [TokenType.endOfFile] token has already been
      44             :   /// consumed.
      45             :   Token peek() {
      46           0 :     if (_next == null) _next = _getNext();
      47           0 :     return _next;
      48             :   }
      49             : 
      50             :   /// Consumes and returns the next token in the stream.
      51             :   ///
      52             :   /// Throws a [StateError] if a [TokenType.endOfFile] token has already been
      53             :   /// consumed.
      54             :   Token next() {
      55           0 :     var token = _next == null ? _getNext() : _next;
      56           0 :     _endOfFileEmitted = token.type == TokenType.endOfFile;
      57           0 :     _next = null;
      58             :     return token;
      59             :   }
      60             : 
      61             :   /// If the next token matches [type], consumes it and returns `true`;
      62             :   /// otherwise, returns `false`.
      63             :   ///
      64             :   /// Throws a [StateError] if a [TokenType.endOfFile] token has already been
      65             :   /// consumed.
      66             :   bool scan(TokenType type) {
      67           0 :     if (peek().type != type) return false;
      68           0 :     next();
      69             :     return true;
      70             :   }
      71             : 
      72             :   /// Scan and return the next token in the stream.
      73             :   Token _getNext() {
      74           0 :     if (_endOfFileEmitted) throw new StateError("No more tokens.");
      75             : 
      76           0 :     _consumeWhitespace();
      77           0 :     if (_scanner.isDone) {
      78           0 :       return new Token(
      79           0 :           TokenType.endOfFile, _scanner.spanFrom(_scanner.state));
      80             :     }
      81             : 
      82           0 :     switch (_scanner.peekChar()) {
      83           0 :       case 0x28 /* ( */: return _scanOperator(TokenType.leftParen);
      84           0 :       case 0x29 /* ) */: return _scanOperator(TokenType.rightParen);
      85           0 :       case 0x3F /* ? */: return _scanOperator(TokenType.questionMark);
      86           0 :       case 0x3A /* : */: return _scanOperator(TokenType.colon);
      87           0 :       case 0x21 /* ! */: return _scanOperator(TokenType.not);
      88           0 :       case 0x7C /* | */: return _scanOr();
      89           0 :       case 0x26 /* & */: return _scanAnd();
      90           0 :       default: return _scanIdentifier();
      91             :     }
      92             :   }
      93             : 
      94             :   /// Scans a single-character operator and returns a token of type [type].
      95             :   ///
      96             :   /// This assumes that the caller has already verified that the next character
      97             :   /// is correct for the given operator.
      98             :   Token _scanOperator(TokenType type) {
      99           0 :     var start = _scanner.state;
     100           0 :     _scanner.readChar();
     101           0 :     return new Token(type, _scanner.spanFrom(start));
     102             :   }
     103             : 
     104             :   /// Scans a `||` operator and returns the appropriate token.
     105             :   ///
     106             :   /// This validates that the next two characters are `||`.
     107             :   Token _scanOr() {
     108           0 :     var start = _scanner.state;
     109           0 :     _scanner.expect("||");
     110           0 :     return new Token(TokenType.or, _scanner.spanFrom(start));
     111             :   }
     112             : 
     113             :   /// Scans a `&&` operator and returns the appropriate token.
     114             :   ///
     115             :   /// This validates that the next two characters are `&&`.
     116             :   Token _scanAnd() {
     117           0 :     var start = _scanner.state;
     118           0 :     _scanner.expect("&&");
     119           0 :     return new Token(TokenType.and, _scanner.spanFrom(start));
     120             :   }
     121             : 
     122             :   /// Scans and returns an identifier token.
     123             :   Token _scanIdentifier() {
     124           0 :     _scanner.expect(_hyphenatedIdentifier, name: "expression");
     125           0 :     return new IdentifierToken(_scanner.lastMatch[0], _scanner.lastSpan);
     126             :   }
     127             : 
     128             :   /// Consumes all whitespace and comments immediately following the cursor's
     129             :   /// current position.
     130             :   void _consumeWhitespace() {
     131           0 :     while (_scanner.scan(_whitespaceAndSingleLineComments) ||
     132           0 :         _multiLineComment()) {
     133             :       // Do nothing.
     134             :     }
     135             :   }
     136             : 
     137             :   /// Consumes a single multi-line comment.
     138             :   ///
     139             :   /// Returns whether or not a comment was consumed.
     140             :   bool _multiLineComment() {
     141           0 :     if (!_scanner.scan("/*")) return false;
     142             : 
     143           0 :     while (_scanner.scan(_multiLineCommentBody) || _multiLineComment()) {
     144             :       // Do nothing.
     145             :     }
     146           0 :     _scanner.expect("*/");
     147             : 
     148             :     return true;
     149             :   }
     150             : }

Generated by: LCOV version 1.13