| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library Peg Parser; | 5 library PegParser; |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * The following functions are combinators for building Rules. | 8 * The following functions are combinators for building Rules. |
| 9 * | 9 * |
| 10 * A rule is one of the following | 10 * A rule is one of the following |
| 11 * - A String which matches the string literally. | 11 * - A String which matches the string literally. |
| 12 * - A Symbol which matches the symbol's definition. | 12 * - A Symbol which matches the symbol's definition. |
| 13 * - A list of rules with an optional reducing function, which matches a sequenc
e. | 13 * - A list of rules with an optional reducing function, which matches a sequenc
e. |
| 14 * - The result of calling one of the combinators. | 14 * - The result of calling one of the combinators. |
| 15 * | 15 * |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 * CHAR does not generate a value. | 55 * CHAR does not generate a value. |
| 56 */ | 56 */ |
| 57 _Rule CHAR([characters]) { | 57 _Rule CHAR([characters]) { |
| 58 if (characters == null) | 58 if (characters == null) |
| 59 return const _AnyCharRule(); | 59 return const _AnyCharRule(); |
| 60 if (characters is int) | 60 if (characters is int) |
| 61 return CHARCODE(characters); | 61 return CHARCODE(characters); |
| 62 | 62 |
| 63 // Find the range of character codes and construct an array of flags for codes | 63 // Find the range of character codes and construct an array of flags for codes |
| 64 // within the range. | 64 // within the range. |
| 65 List<int> codes = characters.codeUnits; | 65 List<int> codes = characters.codeUnits.toList(); |
| 66 codes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); | 66 codes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); |
| 67 int lo = codes[0]; | 67 int lo = codes[0]; |
| 68 int hi = codes[codes.length - 1]; | 68 int hi = codes[codes.length - 1]; |
| 69 if (lo == hi) | 69 if (lo == hi) |
| 70 return CHARCODE(lo); | 70 return CHARCODE(lo); |
| 71 int len = hi - lo + 1; | 71 int len = hi - lo + 1; |
| 72 var flags = new List<bool>(len); | 72 var flags = new List<bool>(len); |
| 73 for (int i = 0; i < len; ++i) | 73 for (int i = 0; i < len; ++i) |
| 74 flags[i] = false; | 74 flags[i] = false; |
| 75 for (int code in codes) | 75 for (int code in codes) |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 158 |
| 159 /** | 159 /** |
| 160 * MANY(rule) matches [rule] [min] or more times. | 160 * MANY(rule) matches [rule] [min] or more times. |
| 161 * [min] must be 0 or 1. | 161 * [min] must be 0 or 1. |
| 162 * If [separator] is provided it is used to match a separator between matches of | 162 * If [separator] is provided it is used to match a separator between matches of |
| 163 * [rule]. | 163 * [rule]. |
| 164 * | 164 * |
| 165 * MANY is a value generating matcher. The value is a list of the matches of | 165 * MANY is a value generating matcher. The value is a list of the matches of |
| 166 * [rule]. The list may be empty if [:min == 0:]. | 166 * [rule]. The list may be empty if [:min == 0:]. |
| 167 */ | 167 */ |
| 168 _Rule MANY(rule, [separator = null, int min = 1]) { | 168 _Rule MANY(rule, {separator: null, int min: 1}) { |
| 169 assert(0 <= min && min <= 1); | 169 assert(0 <= min && min <= 1); |
| 170 return new _RepeatRule(_compile(rule), _compileOptional(separator), min); | 170 return new _RepeatRule(_compile(rule), _compileOptional(separator), min); |
| 171 } | 171 } |
| 172 | 172 |
| 173 /** | 173 /** |
| 174 * Matches [rule] zero or more times. Shorthand for [:MANY(rule, min:0):] | 174 * Matches [rule] zero or more times. Shorthand for [:MANY(rule, min:0):] |
| 175 * TODO: retire min: parameter? | 175 * TODO: retire min: parameter? |
| 176 * | 176 * |
| 177 * MANY0 is a value generating matcher. | 177 * MANY0 is a value generating matcher. |
| 178 */ | 178 */ |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 diagnose(state) { | 267 diagnose(state) { |
| 268 var message = 'unexpected error'; | 268 var message = 'unexpected error'; |
| 269 if (!state.max_rule.isEmpty) { | 269 if (!state.max_rule.isEmpty) { |
| 270 var s = new Set(); | 270 var s = new Set(); |
| 271 for (var rule in state.max_rule) | 271 for (var rule in state.max_rule) |
| 272 s.add(rule.description()); | 272 s.add(rule.description()); |
| 273 var tokens = new List<String>.from(s); | 273 var tokens = new List<String>.from(s); |
| 274 tokens.sort((a, b) => | 274 tokens.sort((a, b) => |
| 275 a.startsWith("'") == b.startsWith("'") | 275 a.startsWith("'") == b.startsWith("'") |
| 276 ? a.compareTo(b) | 276 ? a.compareTo(b) |
| 277 : a.startsWith("'") ? +1 : -1); | 277 : a.startsWith("'") ? 1 : -1); |
| 278 var expected = tokens.join(' or '); | 278 var expected = tokens.join(' or '); |
| 279 var found = state.max_pos == state._end ? 'end of file' | 279 var found = state.max_pos == state._end ? 'end of file' |
| 280 : "'${state._text[state.max_pos]}'"; | 280 : "'${state._text[state.max_pos]}'"; |
| 281 message = 'Expected $expected but found $found'; | 281 message = 'Expected $expected but found $found'; |
| 282 } | 282 } |
| 283 int start = state.max_pos; | 283 int start = state.max_pos; |
| 284 int end = start; | 284 int end = start; |
| 285 while (start >= 1 && state._text[start - 1] != '\n') --start; | 285 while (start >= 1 && state._text[start - 1] != '\n') --start; |
| 286 while (end < state._text.length && state._text[end] != '\n') ++end; | 286 while (end < state._text.length && state._text[end] != '\n') ++end; |
| 287 var line = state._text.substring(start, end); | 287 var line = state._text.substring(start, end); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 307 void set def(rule) { | 307 void set def(rule) { |
| 308 assert(_rule == null); // Assign once. | 308 assert(_rule == null); // Assign once. |
| 309 _rule = _compile(rule); | 309 _rule = _compile(rule); |
| 310 } | 310 } |
| 311 | 311 |
| 312 toString() => _rule == null ? '<$name>' : '<$name = $_rule>'; | 312 toString() => _rule == null ? '<$name>' : '<$name = $_rule>'; |
| 313 } | 313 } |
| 314 | 314 |
| 315 | 315 |
| 316 class _ParserState { | 316 class _ParserState { |
| 317 _ParserState(this._text, [_Rule whitespace = null]) { | 317 _ParserState(this._text, {_Rule whitespace}) { |
| 318 _end = this._text.length; | 318 _end = this._text.length; |
| 319 whitespaceRule = whitespace; | 319 whitespaceRule = whitespace; |
| 320 max_rule = []; | 320 max_rule = []; |
| 321 } | 321 } |
| 322 | 322 |
| 323 String _text; | 323 String _text; |
| 324 int _end; | 324 int _end; |
| 325 | 325 |
| 326 // | 326 // |
| 327 bool inWhitespaceMode = false; | 327 bool inWhitespaceMode = false; |
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 add(s); | 849 add(s); |
| 850 add(t); | 850 add(t); |
| 851 add(u); | 851 add(u); |
| 852 add(v); | 852 add(v); |
| 853 add(w); | 853 add(w); |
| 854 add(x); | 854 add(x); |
| 855 add(y); | 855 add(y); |
| 856 add(z); | 856 add(z); |
| 857 return list; | 857 return list; |
| 858 } | 858 } |
| OLD | NEW |