Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // 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
| |
| 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 function parseMessages(str) { | |
| 6 var result = {}; | |
| 7 var i; | |
| 8 | |
| 9 function cc() { return str.charCodeAt(i); } | |
| 10 | |
| 11 var SPACE = 32; | |
| 12 var NL = 10; | |
| 13 var SLASH = 47; | |
| 14 var SQUOTE = 39; | |
| 15 var DQUOTE = 34; | |
| 16 var LBRACE = 123; // { | |
| 17 var RBRACE = 125; // } | |
| 18 var SEMICOLON = 59; | |
| 19 var COMMA = 44; | |
| 20 var LBRACKET = 91; | |
| 21 var RBRACKET = 93; | |
| 22 var BACK_SLASH = 92; | |
| 23 var $r = 114; | |
| 24 | |
| 25 // Avoid infinite loops with bad data. | |
| 26 var lastNonWhite = -1; | |
| 27 var encounteredSameNonWhite = 0; | |
| 28 | |
| 29 // Moves to the next non-white position (skipping over eol-comments). | |
| 30 function moveToNextNonWhite() { | |
| 31 for (; i < str.length; i++) { | |
| 32 var charCode = cc(); | |
| 33 if (charCode == NL || charCode == SPACE) { | |
| 34 // Do nothing. | |
| 35 } else if (charCode == SLASH && str.charCodeAt(i + 1) == SLASH) { | |
| 36 // Consume until eol. | |
| 37 while (cc() != NL) i++; | |
| 38 } else { | |
| 39 break; | |
| 40 } | |
| 41 } | |
| 42 if (lastNonWhite == i) { | |
| 43 if (encounteredSameNonWhite++ == 10) | |
| 44 throw "bad input " + i; | |
| 45 } else { | |
| 46 encounteredSameNonWhite = 0; | |
| 47 lastNonWhite = i; | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 // Automatically concatenates adjacent string literals. | |
| 52 function parseString() { | |
| 53 var result; | |
| 54 // str[i] == '"', str[i] == "'", or str[i] == "r". | |
| 55 var allowEscapes = true; | |
| 56 var startChar = cc(); | |
| 57 if (startChar == $r) { | |
| 58 i++; | |
| 59 startChar = cc(); | |
| 60 allowEscapes = false; | |
| 61 } | |
| 62 i++; | |
| 63 if (cc() == startChar && str.charCodeAt(i + 1) != startChar) { | |
| 64 // Empty string. | |
| 65 result = ''; | |
| 66 i ++; | |
| 67 } else { | |
| 68 var isMultiline = false; | |
| 69 if (cc() == startChar) { | |
| 70 isMultiline = true; | |
| 71 i += 2; | |
| 72 // 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
| |
| 73 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
| |
| 74 } | |
| 75 var startPos = i; | |
| 76 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.
| |
| 77 var charCode = cc(); | |
| 78 if (allowEscapes && charCode == BACK_SLASH) { | |
| 79 // Ignore next character. | |
| 80 i++; | |
| 81 continue; | |
| 82 } | |
| 83 if (charCode == startChar && | |
| 84 (!isMultiline || | |
| 85 (str.charCodeAt(i + 1) == startChar && | |
| 86 str.charCodeAt(i + 2) == startChar))) { | |
| 87 result = str.substring(startPos, i); | |
| 88 i += isMultiline ? 3 : 1; | |
| 89 break; | |
| 90 } | |
| 91 } | |
| 92 } | |
| 93 moveToNextNonWhite(); | |
| 94 // Another string ?. | |
| 95 charCode = cc(); | |
| 96 if (charCode == SQUOTE || charCode == DQUOTE || charCode == $r) { | |
| 97 result += parseString(); | |
| 98 } | |
| 99 return result; | |
| 100 } | |
| 101 | |
| 102 | |
| 103 function parseValue() { | |
| 104 var charCode = cc(); | |
| 105 if (charCode == SQUOTE || charCode == DQUOTE || | |
| 106 (charCode == $r && | |
| 107 (str.charCodeAt(i + 1) == SQUOTE || | |
| 108 str.charCodeAt(i + 1) == DQUOTE))) { | |
| 109 return parseString(); | |
| 110 } else if (charCode == LBRACE) { | |
| 111 return parseMap(); | |
| 112 } else if (charCode == LBRACKET) { | |
| 113 return parseList(); | |
| 114 } else { | |
| 115 // Assume it's something we don't support (like DONT_KNOW_HOW_TO_FIX). | |
| 116 // Ignore and move to the end of the map. | |
| 117 while (true) { | |
| 118 var charCode = cc(); | |
| 119 if (charCode == RBRACE) break; | |
| 120 if (charCode == RBRACKET) break; | |
| 121 if (charCode == COMMA) break; | |
| 122 i++ | |
| 123 } | |
| 124 return null; | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 function parseList() { | |
| 129 var result = []; | |
| 130 // str[i] == '['. | |
| 131 i++; | |
| 132 moveToNextNonWhite(); | |
| 133 while (cc() != RBRACKET) { | |
| 134 result.push(parseValue()); | |
| 135 moveToNextNonWhite(); | |
| 136 if (cc() == COMMA) { | |
| 137 i++; | |
| 138 moveToNextNonWhite(); | |
| 139 } | |
| 140 } | |
| 141 i++; | |
| 142 return result; | |
| 143 } | |
| 144 | |
| 145 // Parse { 'id': ... } | |
| 146 function parseMap() { | |
| 147 var result = {}; | |
| 148 // str[i] == '{'. | |
| 149 i++; | |
| 150 moveToNextNonWhite(); | |
| 151 while (cc() != RBRACE) { // "}" | |
| 152 var key = parseString(); | |
| 153 moveToNextNonWhite(); | |
| 154 i++; // The ":". | |
|
Johnni Winther
2015/12/11 11:27:29
Assert this?
floitsch
2015/12/14 18:56:40
Done.
| |
| 155 moveToNextNonWhite(); | |
| 156 result[key] = parseValue(); | |
| 157 moveToNextNonWhite(); | |
| 158 if (cc() == COMMA) { | |
| 159 i++; | |
| 160 moveToNextNonWhite(); | |
| 161 } | |
| 162 } | |
| 163 i++; | |
| 164 return result; | |
| 165 } | |
| 166 | |
| 167 // Skip header. | |
| 168 var start = "\nfinal MESSAGES = {"; | |
| 169 var messagesPos = str.indexOf(start); | |
| 170 for (i = messagesPos + start.length; i < str.length; moveToNextNonWhite()) { | |
| 171 var charCode = cc(); | |
| 172 if (charCode == SQUOTE || charCode == DQUOTE) { // '"' or "'" | |
| 173 var name = parseString(); | |
| 174 moveToNextNonWhite(); | |
| 175 i++; // The ":". | |
| 176 moveToNextNonWhite(); | |
| 177 var data = parseMap(); | |
| 178 result[name] = data; | |
| 179 moveToNextNonWhite(); | |
| 180 i++; // The trailing "," or the trailing "}". | |
| 181 } else if (charCode == RBRACE || charCode == SEMICOLON) { // "}" or ";". | |
| 182 break; | |
| 183 } | |
| 184 } | |
| 185 return result; | |
| 186 } | |
| 187 | |
| 188 var messagesUri = | |
| 189 'https://raw.githubusercontent.com/dart-lang/sdk/' + | |
| 190 'master/pkg/dart_messages/lib/shared_messages.dart'; | |
| 191 | |
| 192 function loadMessages(callback, onError, uri) { | |
| 193 if (!onError) onError = function(e) { throw e; }; | |
| 194 if (!uri) uri = messagesUri; | |
| 195 | |
| 196 var request = new XMLHttpRequest(); | |
| 197 request.addEventListener("load", function() { | |
| 198 try { | |
| 199 callback(parseMessages(this.responseText)); | |
| 200 } catch (e) { | |
| 201 onError(e); | |
| 202 } | |
| 203 }); | |
| 204 request.open("GET", uri); | |
| 205 request.send(); | |
| 206 } | |
| OLD | NEW |