Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(908)

Unified Diff: utils/peg/pegparser.dart

Issue 8414016: Revert "PEG Parser: under review at http://codereview.chromium.org/8399029" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « client/dom/scripts/idlrenderer.dart ('k') | utils/peg/pegparser_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/peg/pegparser.dart
diff --git a/utils/peg/pegparser.dart b/utils/peg/pegparser.dart
deleted file mode 100644
index da98b4a050a5d35d40c368340af525f5f7c5a1bc..0000000000000000000000000000000000000000
--- a/utils/peg/pegparser.dart
+++ /dev/null
@@ -1,858 +0,0 @@
-// Copyright (c) 2011, 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.
-
-#library('Peg Parser');
-
-/*
- * The following functions are combinators for building Rules.
- *
- * A rule is one of the following
- * - A String which matches the string literally.
- * - A Symbol which matches the symbol's definition.
- * - A list of rules with an optional reducing function, which matches a sequence.
- * - The result of calling one of the combinators.
- *
- * Some rules are 'value-generating' rules, they return an 'abstract syntax
- * tree' with the match. If a rule is not value-generating [:null:] is the
- * value.
- *
- * A Symbol is always a value-generating rule. If the value is not required, use
- * [:SKIP(aSymbol):] in place of [:aSymbol:].
- *
- * A String is not a value-generating rule but can be converted into one by
- * using [:TEXT('string'):] in place of [:'string':].
- *
- * A list or sequence is value-generating depending on the subrules. The
- * sequence is value-generating if any of the subrules are value-generating or
- * if there is a reducing function. If no reducing function is given, the value
- * returned depends on the number of value-generating subrules. If there is
- * only one value generating subrule, that provideds the value for the sequence.
- * If there are more, then the value is a list of the values of the
- * value-generating subrules.
- */
-
-/**
- * Matches one character by a predicate on the character code.
- * If [spec] is an int, that character is matched.
- * If [spec] is a function it is used
- *
- * Example [: CHARCODE((code) => 48 <= code && code <= 57) :] recognizes an
- * ASCII digit.
- *
- * CHARCODE does not generate a value.
- */
-_Rule CHARCODE(spec, [name]) {
- if (spec is int)
- return new _CharCodeRule((code) => code == spec, name);
- else
- return new _CharCodeRule(spec, name);
-}
-
-/**
- * Matches one of the [characters].
- *
- * CHAR does not generate a value.
- */
-_Rule CHAR([characters]) {
- if (characters == null)
- return const _AnyCharRule();
- if (characters is int)
- return CHARCODE(characters);
-
- // Find the range of character codes and construct an array of flags for codes
- // within the range.
- List<int> codes = characters.charCodes();
- codes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
- int lo = codes[0];
- int hi = codes[codes.length - 1];
- if (lo == hi)
- return CHARCODE(lo);
- int len = hi - lo + 1;
- var flags = new List<bool>(len);
- for (int i = 0; i < len; ++i)
- flags[i] = false;
- for (int code in codes)
- flags[code - lo] = true;
-
- return CHARCODE((code) => code >= lo && code <= hi && flags[code - lo]);
-}
-
-/**
- * Matches the end of the input.
- *
- * END does not generate a value.
- */
-_Rule get END() => new _EndOfInputRule();
-
-/**
- * Throws an exception.
- */
-_Rule ERROR(String message) => new _ErrorRule(message);
-
-/**
- * Matches [rule] but does not consume the input. Useful for matching a right
- * context.
- *
- * AT does not generate a value.
- */
-_Rule AT(rule) => new _ContextRule(_compile(rule));
-
-/**
- * Matches when [rule] does not match. No input is consumed.
- *
- * NOT does not generate a value.
- */
-_Rule NOT(rule) => new _NegativeContextRule(_compile(rule));
-
-/**
- * Matches [rule] but generates no value even if [rule] generates a value.
- *
- * SKIP never generates a value.
- */
-_Rule SKIP(rule) => new _SkipRule(_compile(rule));
-
-/**
- * Matches [rule] in a lexical context where whitespace is not automatically
- * skipped. Useful for matching what would normally be considered to be tokens.
- * [name] is a user-friendly description of what is being matched and is used in
- * error messages.
- *
- * LEX(rule)
- * LEX(name, rule)
- *
- * LEX does not generate a value. If a value is required, wrap LEX with TEXT.
- */
-_Rule LEX(arg1, [arg2]) {
- if (arg2 == null)
- return new _LexicalRule(arg1 is String ? arg1 : null, _compile(arg1));
- else
- return new _LexicalRule(arg1, _compile(arg2));
-}
-
-/**
- * Matches [rule] and generates a value from the matched text. If the [rule]
- * matches, then TEXT(rule) matches and has a value derived from the string
- * fragment that was matched. The default derived value is the string fragment.
- *
- * TEXT always generates a value.
- */
-_Rule TEXT(rule, [extractor]) =>
- new _TextValueRule(_compile(rule),
- extractor == null
- ? (string, start, end) => string.substring(start, end)
- : extractor);
-
-/**
- * Matches an optional rule.
- *
- * MAYBE is a value generating matcher.
- *
- * If [rule] is value generating then the value is the value generated by [rule]
- * if it matches, and [:null:] if it does not.
- *
- * If [rule] is not value generatinge then the value is [:true:] if [rule]
- * matches and [:false:] if it does not.
- */
-_Rule MAYBE(rule) => new _OptionalRule(_compile(rule));
-
-/**
- * MANY(rule) matches [rule] [min] or more times.
- * [min] must be 0 or 1.
- * If [separator] is provided it is used to match a separator between matches of
- * [rule].
- *
- * MANY is a value generating matcher. The value is a list of the matches of
- * [rule]. The list may be empty if [:min == 0:].
- */
-_Rule MANY(rule, [separator = null, int min = 1]) {
- assert(0 <= min && min <= 1);
- return new _RepeatRule(_compile(rule), _compileOptional(separator), min);
-}
-
-/**
- * Matches [rule] zero or more times. Shorthand for [:MANY(rule, min:0):]
- * TODO: retire min: parameter?
- *
- * MANY0 is a value generating matcher.
- */
-_Rule MANY0(rule, [separator = null]) {
- return new _RepeatRule(_compile(rule), _compileOptional(separator), 0);
-}
-
-/**
- * Matches [rules] in order until one succeeds.
- *
- * OR is value-generating.
- */
-_Rule OR([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]) =>
- _compileMultiRule(
- (a is List && b == null) // Backward compat. OR([a, b]) => OR(a, b).
- ? a
- : _unspread(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z),
- false,
- (compiledRules, valueCount, reducer) =>
- new _ChoiceRule(compiledRules));
-
-
-
-_Rule SEQ([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]) =>
- _compile(_unspread(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z));
-
-/**
- * Matches [rule]
- */
-_Rule MEMO(rule) => new _MemoRule(_compile(rule));
-
-_Rule TAG(tag, rule) => _compile([rule, (ast) => [tag, ast]]);
-
-
-class ParseError implements Exception {
- const ParseError(String this._message);
- String toString() => _message;
- final String _message;
-}
-
-/**
- * A grammar is a collection of symbols and rules that may be used to parse an
- * input.
- */
-class Grammar {
- Map<String, Symbol> _symbols;
-
- /** This rule may be set by the user to define whitespace. */
- _Rule _whitespace;
-
- _Rule get whitespace() => _whitespace;
- void set whitespace(rule) { _whitespace = _compile(rule); }
-
- Grammar() {
- _symbols = new Map<String, Symbol>();
- whitespace = CHAR(' \t\r\n');
- }
-
- /**
- * operator [] is used to find or create symbols. Symbols may appear in rules
- * to define recursive rules.
- */
- Symbol operator [](String name) {
- if (_symbols.containsKey(name))
- return _symbols[name];
- Symbol s = new Symbol(name, this);
- _symbols[name] = s;
- return s;
- }
-
- /**
- * Parses the input string and returns the parsed AST, or throws an exception
- * if the input can't be parsed.
- */
- parse(root, String text) {
- for (var symbol in _symbols.getValues())
- if (symbol._rule == null)
- print('${symbol.name} is undefined');
-
- var state = new _ParserState(text, whitespace: whitespace);
- var match = _compile(root).match(state, 0);
- if (match == null)
- return diagnose(state);
- var pos = match[0];
- pos = _skip_whitespace(state, pos);
- if (pos == state._end)
- return match[1];
- // TODO: Make this complain about expecting end of file.
- return diagnose(state);
- }
-
- diagnose(state) {
- var message = 'unexpected error';
- if (!state.max_rule.isEmpty()) {
- var s = new Set();
- for (var rule in state.max_rule)
- s.add(rule.description());
- var tokens = new List<String>.from(s);
- tokens.sort((a, b) =>
- a.startsWith("'") == b.startsWith("'")
- ? a.compareTo(b)
- : a.startsWith("'") ? +1 : -1);
- var expected = Strings.join(tokens, ' or ');
- var found = state.max_pos == state._end ? 'end of file'
- : "'${state._text[state.max_pos]}'";
- message = 'Expected $expected but found $found';
- }
- int start = state.max_pos;
- int end = start;
- while (start >= 1 && state._text[start - 1] != '\n') --start;
- while (end < state._text.length && state._text[end] != '\n') ++end;
- var line = state._text.substring(start, end);
- var indicator = '';
- for (var i = 0; i < line.length && start + i < state.max_pos; i++)
- indicator = indicator + ' ';
- indicator = indicator + '^';
- // TODO: Convert to an exception.
- print(message);
- print(line);
- print(indicator);
- return null;
- }
-}
-
-class Symbol {
- final String name;
- final Grammar grammar;
- _Rule _rule;
-
- Symbol(this.name, this.grammar);
-
- void set def(rule) {
- assert(_rule == null); // Assign once.
- _rule = _compile(rule);
- }
-
- toString() => _rule == null ? '<$name>' : '<$name = $_rule>';
-}
-
-
-class _ParserState {
- _ParserState(this._text, [_Rule whitespace = null]) {
- _end = this._text.length;
- whitespaceRule = whitespace;
- max_rule = [];
- }
-
- String _text;
- int _end;
-
- //
- bool inWhitespaceMode = false;
- _Rule whitespaceRule = null;
-
- // Used for constructing an error message.
- int inhibitExpectedTrackingDepth = 0;
- int max_pos = 0;
- var max_rule;
-}
-
-/**
- * An interface tag for rules. If this tag is on a rule, then the description()
- * of the rule is something sensible to put in a message.
- */
-interface _Expectable {
- String description();
-}
-
-class _Rule {
- const _Rule();
- // Returns null for a match failure or [pos, ast] for success.
- match(_ParserState state, int pos) {
- if (! state.inWhitespaceMode) {
- pos = _skip_whitespace(state, pos);
- }
- return matchAfterWS(state, pos);
- }
-
- // Faster entry point for matching a sub-rule that is matched to the start
- // position of the super-rule. Whitespace has already been skipped so no need
- // to try to skip it again.
- matchAfterWS(_ParserState state, int pos) {
- if (state.inhibitExpectedTrackingDepth == 0) {
- // Track position for possible error messaging
- if (pos > state.max_pos) {
- // Store position and the rule.
- state.max_pos = pos;
- if (this is _Expectable) {
- state.max_rule = [this];
- } else {
- state.max_rule = [];
- }
- } else if (pos == state.max_pos) {
- if (this is _Expectable) {
- state.max_rule.add(this);
- }
- }
- }
- // Delegate the matching logic to the the specialized function.
- return _match(state, pos);
- }
-
- // Overridden in subclasses to match the rule.
- _match(_ParserState state, int pos) => null;
-
- // Does the rule generate a value (AST) with the match?
- bool get generatesValue() => false;
-
- get defaultValue() => null;
-}
-
-int _skip_whitespace(state, pos) {
- // Returns the next non-whitespace position.
- // This is done by matching the optional whitespaceRule with the current text.
- if (state.whitespaceRule == null)
- return pos;
- state.inWhitespaceMode = true;
- state.inhibitExpectedTrackingDepth++;
- while (true) {
- var match = state.whitespaceRule.match(state, pos);
- if (match == null)
- break;
- pos = match[0];
- }
- state.inWhitespaceMode = false;
- state.inhibitExpectedTrackingDepth--;
- return pos;
-}
-
-
-_Rule _compileOptional(rule) {
- return rule == null ? null : _compile(rule);
-}
-
-_Rule _compile(rule) {
- if (rule is _Rule)
- return rule;
- if (rule is String)
- return new _StringRule(rule);
- if (rule is Symbol)
- return new _SymbolRule(rule);
- if (rule is RegExp)
- return new _RegExpRule(rule);
- if (rule is List) {
- return _compileMultiRule(
- rule, true,
- (compiledRules, valueCount, reducer) =>
- new _SequenceRule(compiledRules, valueCount, reducer));
- }
- throw new Exception('Cannot compile rule: $rule');
-}
-
-class _EndOfInputRule extends _Rule {
- _match(_ParserState state, int pos) {
- if (pos == state._end)
- return [pos, null];
- return null;
- }
-
- toString() => 'END';
-}
-
-class _ErrorRule extends _Rule {
- String message;
- _ErrorRule(String this.message);
- _match(_ParserState state, int pos) {
- throw new ParseError(message);
- }
-
- toString() => 'ERROR($message)';
-}
-
-class _CharCodeRule extends _Rule {
- Function _predicate;
- var _name;
- _CharCodeRule(this._predicate, this._name);
- _match(_ParserState state, int pos) {
- if (pos == state._end)
- return null;
- int code = state._text.charCodeAt(pos);
- if (_predicate(code))
- return [pos + 1, null];
- return null;
- }
-
- toString() => _name == null ? 'CHARCODE($_predicate)' : 'CHARCODE($_name)';
-}
-
-class _AnyCharRule extends _Rule {
- const _AnyCharRule();
- _match(_ParserState state, int pos) {
- if (pos == state._end)
- return null;
- return [pos + 1, null];
- }
-
- toString() => 'CHAR()';
-}
-
-class _SymbolRule extends _Rule {
- final Symbol _symbol;
- _SymbolRule(Symbol this._symbol);
- _match(_ParserState state, int pos) {
- if (_symbol._rule == null)
- throw new Exception("Symbol '${_symbol.name}' is undefined");
- return _symbol._rule.match(state, pos);
- }
-
- bool get generatesValue() => true;
-
- toString() => '<${_symbol.name}>';
-}
-
-class _SkipRule extends _Rule {
- // A rule that has no value.
- _Rule _rule;
- _SkipRule(_Rule this._rule);
- _match(_ParserState state, int pos) {
- var match = _rule.matchAfterWS(state, pos);
- if (match == null)
- return null;
- return [match[0], null];
- }
-
- toString() => 'TOKEN($_rule)';
-}
-
-class _StringRule extends _Rule implements _Expectable {
- final String _string;
- int _len;
- _StringRule(this._string) {
- _len = _string.length;
- }
-
- _match(_ParserState state, int pos) {
- if (pos + _len > state._end)
- return null;
- for (int i = 0; i < _len; i++) {
- if (state._text.charCodeAt(pos + i) != _string.charCodeAt(i))
- return null;
- }
- return [pos + _len, null];
- }
-
- //get defaultValue() => _string;
-
- toString() => '"$_string"';
-
- description() => "'$_string'";
-}
-
-class _RegExpRule extends _Rule {
- RegExp _re;
- _RegExpRule(this._re) {
- // There is no convenient way to match an anchored substring.
- throw new Exception('RegExp matching not supported');
- }
-
- toString() => '"$_re"';
-}
-
-class _LexicalRule extends _Rule implements _Expectable {
- final String _name;
- final _Rule _rule;
-
- _LexicalRule(String this._name, _Rule this._rule);
-
- _match(_ParserState state, int pos) {
- state.inWhitespaceMode = true;
- state.inhibitExpectedTrackingDepth++;
- var match = _rule.matchAfterWS(state, pos);
- state.inhibitExpectedTrackingDepth--;
- state.inWhitespaceMode = false;
- return match;
- }
-
- toString() => _name;
-
- description() => _name == null ? '?' : _name;
-}
-
-class _TextValueRule extends _Rule {
- final _Rule _rule;
- final _extract; // Function
-
- _TextValueRule(_Rule this._rule, Function this._extract);
-
- _match(_ParserState state, int pos) {
- var match = _rule.matchAfterWS(state, pos);
- if (match == null) {
- return null;
- }
- var endPos = match[0];
- return [endPos, _extract(state._text, pos, endPos)];
- }
-
- bool get generatesValue() => true;
-
- toString() => 'TEXT($_rule)';
-}
-
-_Rule _compileMultiRule(List rules,
- bool allowReducer,
- finish(compiledRules, valueCount, reducer)) {
- int valueCount = 0;
- List compiledRules = new List<_Rule>();
- Function reducer;
- for (var rule in rules) {
- if (reducer != null)
- throw new Exception('Reducer must be last in sequence: $rule');
- if (rule is Function) {
- if (allowReducer)
- reducer = rule;
- else
- throw new Exception('Bad rule: "$rule"');
- } else {
- _Rule compiledRule = _compile(rule);
- if (compiledRule.generatesValue)
- ++valueCount;
- compiledRules.add(compiledRule);
- }
- }
- return finish(compiledRules, valueCount, reducer);
-}
-
-String _formatMultiRule(String functor, List rules) {
- var sb = new StringBuffer(functor);
- sb.add('(');
- var separator = '';
- for (var rule in rules) {
- sb.add(separator);
- sb.add(rule);
- separator = ',';
- }
- sb.add(')');
- return sb.toString();
-}
-
-class _SequenceRule extends _Rule {
- // This rule matches the component rules in order.
- final List<_Rule> _rules;
- final int _generatingSubRules = 0;
- final Function _reducer;
- bool _generatesValue;
- _SequenceRule(List<_Rule> this._rules,
- int this._generatingSubRules,
- Function this._reducer) {
- _generatesValue = _generatingSubRules > 0 || _reducer != null;
- }
-
- _match(state, pos) {
- var sequence = [];
- for (var rule in _rules) {
- var match = rule.match(state, pos);
- if (match == null)
- return null;
- if (rule.generatesValue) {
- var ast = match[1];
- sequence.add(ast);
- }
- pos = match[0];
- }
- if (_reducer == null) {
- if (_generatingSubRules == 0)
- return [pos, null];
- if (_generatingSubRules == 1)
- return [pos, sequence[0]];
- return [pos, sequence];
- } else {
- return [pos, _apply(_reducer, sequence)];
- }
- }
-
- bool get generatesValue() => _generatesValue;
-
- toString() => _formatMultiRule('SEQ', _rules);
-}
-
-class _ChoiceRule extends _Rule {
- // This rule matches the first component rule that matches.
- List<_Rule> _rules;
- _ChoiceRule(List<_Rule> this._rules);
-
- _match(state, pos) {
- for (var rule in _rules) {
- var match = rule.match(state, pos);
- if (match != null) {
- /*
- if (!rule.generatesValue) {
- var value = rule.defaultValue;
- if (value != null)
- return [match[0], value];
- }
- */
- return match;
- }
- }
- return null;
- }
-
- bool get generatesValue() => true;
-
- toString() => _formatMultiRule('OR', _rules);
-}
-
-class _OptionalRule extends _Rule {
- _Rule _rule;
- _OptionalRule(_Rule this._rule);
- _match(_ParserState state, int pos) {
- var match = _rule.match(state, pos);
- if (_rule.generatesValue)
- return match == null
- ? [pos, null]
- : match;
- return match == null
- ? [pos, false]
- : [match[0], true];
- }
-
- bool get generatesValue() => true;
-
- toString() => 'MAYBE($_rule)';
-}
-
-class _ContextRule extends _Rule {
- _Rule _rule;
- _ContextRule(_Rule this._rule);
- _match(_ParserState state, int pos) {
- // TODO: protect error state.
- var match = _rule._match(state, pos);
- if (match == null)
- return null;
- return [pos, null];
- }
-
- toString() => 'AT($_rule)';
-}
-
-class _NegativeContextRule extends _Rule {
- _Rule _rule;
- _NegativeContextRule(_Rule this._rule);
- _match(_ParserState state, int pos) {
- // TODO: protect error state.
- var match = _rule._match(state, pos);
- if (match == null)
- return [pos, null];
- return null;
- }
-
- toString() => 'NOT($_rule)';
-}
-
-class _RepeatRule extends _Rule {
- // Matches zero, one or more items.
- _Rule _rule;
- _Rule _separator;
- int _min;
-
- _RepeatRule(this._rule, this._separator, this._min);
-
- _match(state, pos) {
- // First match.
- var match = _rule.match(state, pos);
- if (match == null)
- if (_min == 0)
- return [pos, []];
- else
- return null;
- pos = match[0];
- var result = [match[1]];
-
- // Subsequent matches:
- while (true) {
- var newPos = pos;
- if (_separator != null) {
- match = _separator.match(state, pos);
- if (match == null)
- return [pos, result];
- newPos = match[0];
- }
- match = _rule.match(state, newPos);
- if (match == null)
- return [pos, result];
- pos = match[0];
- result.add(match[1]);
- }
- }
-
- bool get generatesValue() => true;
-
- toString() => 'MANY(min:$_min, $_rule${_separator==null?'':", sep: $_separator"})';
-}
-
-class _MemoRule extends _Rule {
- final _Rule _rule;
-
- var parseInstance;
-
- // A map from position to result. Can this be replaced with something
- // smaller?
- // TODO: figure out how to discard the map and parseInstance after parsing.
- Map<int,Object> map;
-
- _MemoRule(this._rule);
-
- _match(state, pos) {
- // See if we are still parsing the same input. Relies on the fact that the
- // input is a string and strings are immutable.
- if (parseInstance !== state._text) {
- map = new Map<int,Object>();
- parseInstance = state._text;
- }
- // TODO: does this have to check or preserve parse state (like
- // inWhitespaceMode, error position info etc?)
- // Stored result can be null (memoized failure).
- if (map.containsKey(pos)) {
- return map[pos];
- }
- var match = _rule.match(state, pos);
- map[pos] = match;
- return match;
- }
-
- bool get generatesValue() => _rule.generatesValue;
-
- toString() => 'MEMO($_rule)';
-}
-
-_apply(fn, List args) {
- switch (args.length) {
- case 0: return fn();
- case 1: return fn(args[0]);
- case 2: return fn(args[0], args[1]);
- case 3: return fn(args[0], args[1], args[2]);
- case 4: return fn(args[0], args[1], args[2], args[3]);
- case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
- case 6: return fn(args[0], args[1], args[2], args[3], args[4],
- args[5]);
- case 7: return fn(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6]);
- case 8: return fn(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7]);
- case 9: return fn(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7], args[8]);
- case 10: return fn(args[0], args[1], args[2], args[3], args[4],
- args[5], args[6], args[7], args[8], args[9]);
-
- default:
- throw new Exception('Too many arguments in _apply: $args');
- }
-}
-
-List _unspread(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) {
- List list = new List();
- add(element) { if (element != null) list.add(element); }
- add(a);
- add(b);
- add(c);
- add(d);
- add(e);
- add(f);
- add(g);
- add(h);
- add(i);
- add(j);
- add(k);
- add(l);
- add(m);
- add(n);
- add(o);
- add(p);
- add(q);
- add(r);
- add(s);
- add(t);
- add(u);
- add(v);
- add(w);
- add(x);
- add(y);
- add(z);
- return list;
-}
« no previous file with comments | « client/dom/scripts/idlrenderer.dart ('k') | utils/peg/pegparser_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698