Index: pkg/dart_messages/lib/parser.js |
diff --git a/pkg/dart_messages/lib/parser.js b/pkg/dart_messages/lib/parser.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f48197e7ea39af0df004b55e58f9374b1d320eea |
--- /dev/null |
+++ b/pkg/dart_messages/lib/parser.js |
@@ -0,0 +1,206 @@ |
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
Johnni Winther
2015/12/11 11:27:29
Why make a parser in JS? Who will use this?
floitsch
2015/12/14 18:56:40
See https://github.com/floitschG/messages and http
Siggi Cherem (dart-lang)
2015/12/14 22:12:07
I wonder whether people will forget that they are
|
+// 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. |
+ |
+function parseMessages(str) { |
+ var result = {}; |
+ var i; |
+ |
+ function cc() { return str.charCodeAt(i); } |
+ |
+ var SPACE = 32; |
+ var NL = 10; |
+ var SLASH = 47; |
+ var SQUOTE = 39; |
+ var DQUOTE = 34; |
+ var LBRACE = 123; // { |
+ var RBRACE = 125; // } |
+ var SEMICOLON = 59; |
+ var COMMA = 44; |
+ var LBRACKET = 91; |
+ var RBRACKET = 93; |
+ var BACK_SLASH = 92; |
+ var $r = 114; |
+ |
+ // Avoid infinite loops with bad data. |
+ var lastNonWhite = -1; |
+ var encounteredSameNonWhite = 0; |
+ |
+ // Moves to the next non-white position (skipping over eol-comments). |
+ function moveToNextNonWhite() { |
+ for (; i < str.length; i++) { |
+ var charCode = cc(); |
+ if (charCode == NL || charCode == SPACE) { |
+ // Do nothing. |
+ } else if (charCode == SLASH && str.charCodeAt(i + 1) == SLASH) { |
+ // Consume until eol. |
+ while (cc() != NL) i++; |
+ } else { |
+ break; |
+ } |
+ } |
+ if (lastNonWhite == i) { |
+ if (encounteredSameNonWhite++ == 10) |
+ throw "bad input " + i; |
+ } else { |
+ encounteredSameNonWhite = 0; |
+ lastNonWhite = i; |
+ } |
+ } |
+ |
+ // Automatically concatenates adjacent string literals. |
+ function parseString() { |
+ var result; |
+ // str[i] == '"', str[i] == "'", or str[i] == "r". |
+ var allowEscapes = true; |
+ var startChar = cc(); |
+ if (startChar == $r) { |
+ i++; |
+ startChar = cc(); |
+ allowEscapes = false; |
+ } |
+ i++; |
+ if (cc() == startChar && str.charCodeAt(i + 1) != startChar) { |
+ // Empty string. |
+ result = ''; |
+ i ++; |
+ } else { |
+ var isMultiline = false; |
+ if (cc() == startChar) { |
+ isMultiline = true; |
+ i += 2; |
+ // Multilines ignore the first new line. |
Johnni Winther
2015/12/11 11:27:29
Shouldn't you ignore whitespaces until the first n
floitsch
2015/12/14 18:56:40
We don't need to follow the exact specification (i
|
+ if (cc() == NL) i++; |
Johnni Winther
2015/12/11 11:27:29
Remember our source files are converted to platfor
floitsch
2015/12/14 18:56:40
I'm now treating "CR" as whitespace. Should make i
|
+ } |
+ var startPos = i; |
+ for (; i < str.length; i++) { |
Johnni Winther
2015/12/11 11:27:29
A file ending with an unterminated string will jus
floitsch
2015/12/14 18:56:40
Done.
|
+ var charCode = cc(); |
+ if (allowEscapes && charCode == BACK_SLASH) { |
+ // Ignore next character. |
+ i++; |
+ continue; |
+ } |
+ if (charCode == startChar && |
+ (!isMultiline || |
+ (str.charCodeAt(i + 1) == startChar && |
+ str.charCodeAt(i + 2) == startChar))) { |
+ result = str.substring(startPos, i); |
+ i += isMultiline ? 3 : 1; |
+ break; |
+ } |
+ } |
+ } |
+ moveToNextNonWhite(); |
+ // Another string ?. |
+ charCode = cc(); |
+ if (charCode == SQUOTE || charCode == DQUOTE || charCode == $r) { |
+ result += parseString(); |
+ } |
+ return result; |
+ } |
+ |
+ |
+ function parseValue() { |
+ var charCode = cc(); |
+ if (charCode == SQUOTE || charCode == DQUOTE || |
+ (charCode == $r && |
+ (str.charCodeAt(i + 1) == SQUOTE || |
+ str.charCodeAt(i + 1) == DQUOTE))) { |
+ return parseString(); |
+ } else if (charCode == LBRACE) { |
+ return parseMap(); |
+ } else if (charCode == LBRACKET) { |
+ return parseList(); |
+ } else { |
+ // Assume it's something we don't support (like DONT_KNOW_HOW_TO_FIX). |
+ // Ignore and move to the end of the map. |
+ while (true) { |
+ var charCode = cc(); |
+ if (charCode == RBRACE) break; |
+ if (charCode == RBRACKET) break; |
+ if (charCode == COMMA) break; |
+ i++ |
+ } |
+ return null; |
+ } |
+ } |
+ |
+ function parseList() { |
+ var result = []; |
+ // str[i] == '['. |
+ i++; |
+ moveToNextNonWhite(); |
+ while (cc() != RBRACKET) { |
+ result.push(parseValue()); |
+ moveToNextNonWhite(); |
+ if (cc() == COMMA) { |
+ i++; |
+ moveToNextNonWhite(); |
+ } |
+ } |
+ i++; |
+ return result; |
+ } |
+ |
+ // Parse { 'id': ... } |
+ function parseMap() { |
+ var result = {}; |
+ // str[i] == '{'. |
+ i++; |
+ moveToNextNonWhite(); |
+ while (cc() != RBRACE) { // "}" |
+ var key = parseString(); |
+ moveToNextNonWhite(); |
+ i++; // The ":". |
Johnni Winther
2015/12/11 11:27:29
Assert this?
floitsch
2015/12/14 18:56:40
Done.
|
+ moveToNextNonWhite(); |
+ result[key] = parseValue(); |
+ moveToNextNonWhite(); |
+ if (cc() == COMMA) { |
+ i++; |
+ moveToNextNonWhite(); |
+ } |
+ } |
+ i++; |
+ return result; |
+ } |
+ |
+ // Skip header. |
+ var start = "\nfinal MESSAGES = {"; |
+ var messagesPos = str.indexOf(start); |
+ for (i = messagesPos + start.length; i < str.length; moveToNextNonWhite()) { |
+ var charCode = cc(); |
+ if (charCode == SQUOTE || charCode == DQUOTE) { // '"' or "'" |
+ var name = parseString(); |
+ moveToNextNonWhite(); |
+ i++; // The ":". |
+ moveToNextNonWhite(); |
+ var data = parseMap(); |
+ result[name] = data; |
+ moveToNextNonWhite(); |
+ i++; // The trailing "," or the trailing "}". |
+ } else if (charCode == RBRACE || charCode == SEMICOLON) { // "}" or ";". |
+ break; |
+ } |
+ } |
+ return result; |
+} |
+ |
+var messagesUri = |
+ 'https://raw.githubusercontent.com/dart-lang/sdk/' + |
+ 'master/pkg/dart_messages/lib/shared_messages.dart'; |
+ |
+function loadMessages(callback, onError, uri) { |
+ if (!onError) onError = function(e) { throw e; }; |
+ if (!uri) uri = messagesUri; |
+ |
+ var request = new XMLHttpRequest(); |
+ request.addEventListener("load", function() { |
+ try { |
+ callback(parseMessages(this.responseText)); |
+ } catch (e) { |
+ onError(e); |
+ } |
+ }); |
+ request.open("GET", uri); |
+ request.send(); |
+} |