| Index: frog/leg/string_validator.dart
|
| ===================================================================
|
| --- frog/leg/string_validator.dart (revision 5925)
|
| +++ frog/leg/string_validator.dart (working copy)
|
| @@ -1,187 +0,0 @@
|
| -// Copyright (c) 2012, 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.
|
| -
|
| -// Check the validity of string literals.
|
| -
|
| -#library("stringvalidator");
|
| -
|
| -#import("leg.dart");
|
| -#import("scanner/scannerlib.dart");
|
| -#import("tree/tree.dart");
|
| -#import("elements/elements.dart");
|
| -#import("util/characters.dart");
|
| -
|
| -class StringValidator {
|
| - final DiagnosticListener listener;
|
| -
|
| - StringValidator(this.listener);
|
| -
|
| - DartString validateQuotedString(Token token) {
|
| - SourceString source = token.value;
|
| - StringQuoting quoting = quotingFromString(source);
|
| - int leftQuote = quoting.leftQuoteLength;
|
| - int rightQuote = quoting.rightQuoteLength;
|
| - SourceString content = source.copyWithoutQuotes(leftQuote, rightQuote);
|
| - return validateString(token,
|
| - token.charOffset + leftQuote,
|
| - content,
|
| - quoting);
|
| - }
|
| -
|
| - DartString validateInterpolationPart(Token token, StringQuoting quoting,
|
| - [bool isFirst = false,
|
| - bool isLast = false]) {
|
| - SourceString source = token.value;
|
| - int leftQuote = 0;
|
| - int rightQuote = 0;
|
| - if (isFirst) leftQuote = quoting.leftQuoteLength;
|
| - if (isLast) rightQuote = quoting.rightQuoteLength;
|
| - SourceString content = source.copyWithoutQuotes(leftQuote, rightQuote);
|
| - return validateString(token,
|
| - token.charOffset + leftQuote,
|
| - content,
|
| - quoting);
|
| - }
|
| -
|
| - static StringQuoting quotingFromString(SourceString sourceString) {
|
| - Iterator<int> source = sourceString.iterator();
|
| - bool raw = false;
|
| - int quoteLength = 1;
|
| - int quoteChar = source.next();
|
| - if (quoteChar == $AT) {
|
| - raw = true;
|
| - quoteChar = source.next();
|
| - }
|
| - assert(quoteChar === $SQ || quoteChar === $DQ);
|
| - // String has at least one quote. Check it if has three.
|
| - // If it only have two, the string must be an empty string literal,
|
| - // and end after the second quote.
|
| - bool multiline = false;
|
| - if (source.hasNext() && source.next() === quoteChar && source.hasNext()) {
|
| - int code = source.next();
|
| - assert(code === quoteChar); // If not, there is a bug in the parser.
|
| - quoteLength = 3;
|
| - // Check if a multiline string starts with a newline (CR, LF or CR+LF).
|
| - if (source.hasNext()) {
|
| - code = source.next();
|
| - if (code === $CR) {
|
| - quoteLength += 1;
|
| - if (source.hasNext() && source.next() === $LF) {
|
| - quoteLength += 1;
|
| - }
|
| - } else if (code === $LF) {
|
| - quoteLength += 1;
|
| - }
|
| - }
|
| - }
|
| - return StringQuoting.getQuoting(quoteChar, raw, quoteLength);
|
| - }
|
| -
|
| - void stringParseError(String message, Token token, int offset) {
|
| - listener.cancel("$message @ $offset", token : token);
|
| - }
|
| -
|
| - /**
|
| - * Validates the escape sequences and special characters of a string literal.
|
| - * Returns a DartString if valid, and null if not.
|
| - */
|
| - DartString validateString(Token token,
|
| - int startOffset,
|
| - SourceString string,
|
| - StringQuoting quoting) {
|
| - // We only need to check for invalid x and u escapes, for line
|
| - // terminators in non-multiline strings, and for invalid Unicode
|
| - // scalar values (either directly or as u-escape values).
|
| - int length = 0;
|
| - int index = startOffset;
|
| - bool containsEscape = false;
|
| - for(Iterator<int> iter = string.iterator(); iter.hasNext(); length++) {
|
| - index++;
|
| - int code = iter.next();
|
| - if (code === $BACKSLASH) {
|
| - if (quoting.raw) continue;
|
| - containsEscape = true;
|
| - if (!iter.hasNext()) {
|
| - stringParseError("Incomplete escape sequence",token, index);
|
| - return null;
|
| - }
|
| - index++;
|
| - code = iter.next();
|
| - if (code === $x) {
|
| - for (int i = 0; i < 2; i++) {
|
| - if (!iter.hasNext()) {
|
| - stringParseError("Incomplete escape sequence", token, index);
|
| - return null;
|
| - }
|
| - index++;
|
| - code = iter.next();
|
| - if (!isHexDigit(code)) {
|
| - stringParseError("Invalid character in escape sequence",
|
| - token, index);
|
| - return null;
|
| - }
|
| - }
|
| - // A two-byte hex escape can't generate an invalid value.
|
| - continue;
|
| - } else if (code === $u) {
|
| - int escapeStart = index - 1;
|
| - index++;
|
| - code = iter.next();
|
| - int value = 0;
|
| - if (code == $OPEN_CURLY_BRACKET) {
|
| - // expect 1-6 hex digits.
|
| - int count = 0;
|
| - index++;
|
| - code = iter.next();
|
| - do {
|
| - if (!isHexDigit(code)) {
|
| - stringParseError("Invalid character in escape sequence",
|
| - token, index);
|
| - return null;
|
| - }
|
| - count++;
|
| - value = value * 16 + hexDigitValue(code);
|
| - index++;
|
| - code = iter.next();
|
| - } while (code != $CLOSE_CURLY_BRACKET);
|
| - if (count > 6) {
|
| - stringParseError("Invalid character in escape sequence",
|
| - token, index - (count - 6));
|
| - return null;
|
| - }
|
| - } else {
|
| - // Expect four hex digits, including the one just read.
|
| - for (int i = 0; i < 4; i++) {
|
| - if (i > 0) {
|
| - index++;
|
| - code = iter.next();
|
| - }
|
| - if (!isHexDigit(code)) {
|
| - stringParseError("Invalid character in escape sequence",
|
| - token, index);
|
| - return null;
|
| - }
|
| - value = value * 16 + hexDigitValue(code);
|
| - }
|
| - }
|
| - code = value;
|
| - }
|
| - }
|
| - // This handles both unescaped characters and the value of unicode
|
| - // escapes.
|
| - if (!isUnicodeScalarValue(code)) {
|
| - stringParseError(
|
| - "Invalid Unicode scalar value U+${code.toRadixString(16)}",
|
| - token, index);
|
| - return null;
|
| - }
|
| - }
|
| - // String literal successfully validated.
|
| - if (quoting.raw || !containsEscape) {
|
| - // A string without escapes could just as well have been raw.
|
| - return new DartString.rawString(string, length);
|
| - }
|
| - return new DartString.escapedString(string, length);
|
| - }
|
| -}
|
|
|