| // Copyright (c) 2013, 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. |
| |
| part of dart._internal; |
| |
| /** |
| * Implementation of [core.Symbol]. This class uses the same name as |
| * a core class so a user can't tell the difference. |
| * |
| * The purpose of this class is to hide [_name] from user code, but |
| * make it accessible to Dart platform code via the static method |
| * [getName]. |
| */ |
| class Symbol implements core.Symbol { |
| final String _name; |
| |
| /** |
| * Source of RegExp matching Dart reserved words. |
| * |
| * Reserved words are not allowed as identifiers. |
| */ |
| static const String reservedWordRE = |
| r'(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|' |
| r'e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|' |
| r'ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|' |
| r'v(?:ar|oid)|w(?:hile|ith))'; |
| /** |
| * Source of RegExp matching any public identifier. |
| * |
| * A public identifier is a valid identifier (not a reserved word) |
| * that doesn't start with '_'. |
| */ |
| static const String publicIdentifierRE = |
| r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$][\w$]*'; |
| /** |
| * Source of RegExp matching any identifier. |
| * |
| * It matches identifiers but not reserved words. The identifiers |
| * may start with '_'. |
| */ |
| static const String identifierRE = |
| r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$_][\w$]*'; |
| /** |
| * Source of RegExp matching a declarable operator names. |
| * |
| * The operators that can be declared using `operator` declarations are |
| * also the only ones allowed as symbols. The name of the operators is |
| * the same as the operator itself except for unary minus, where the name |
| * is "unary-". |
| */ |
| static const String operatorRE = |
| r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>(?:|=|>>?)|unary-)'; |
| |
| // Grammar if symbols: |
| // symbol ::= qualifiedName | <empty> |
| // qualifiedName ::= publicIdentifier '.' qualifiedName | name |
| // name ::= publicIdentifier |
| // | publicIdentifier '=' |
| // | operator |
| // where publicIdentifier is any valid identifier (not a reserved word) |
| // that isn't private (doesn't start with '_'). |
| // |
| // Railroad diagram of the accepted grammar: |
| // |
| // /----------------\ |
| // | | |
| // | /-[.]-/ /-[=]-\ |
| // \ / / \ |
| // -------[id]-------------------------> |
| // \ / |
| // \------[operator]---/ |
| // \ / |
| // \------------/ |
| // |
| |
| /** |
| * RegExp that validates a non-empty non-private symbol. |
| * |
| * The empty symbol is handled before this regexp is used, and is not |
| * accepted. |
| */ |
| static final RegExp publicSymbolPattern = new RegExp( |
| '^(?:$operatorRE\$|$publicIdentifierRE(?:=?\$|[.](?!\$)))+?\$'); |
| |
| // The grammar of symbols that may be private is the same as for public |
| // symbols, except that "publicIdentifier" is replaced by "identifier", |
| // which matches any identifier. |
| |
| /** |
| * RegExp that validates a non-empty symbol. |
| * |
| * Private symbols are accepted. |
| * |
| * The empty symbol is handled before this regexp is used, and is not |
| * accepted. |
| */ |
| static final RegExp symbolPattern = |
| new RegExp('^(?:$operatorRE\$|$identifierRE(?:=?\$|[.](?!\$)))+?\$'); |
| |
| external const Symbol(String name); |
| |
| /** |
| * Platform-private method used by the mirror system to create |
| * otherwise invalid names. |
| */ |
| const Symbol.unvalidated(this._name); |
| |
| // This is called by dart2js. |
| Symbol.validated(String name) : this._name = validatePublicSymbol(name); |
| |
| bool operator ==(Object other) => other is Symbol && _name == other._name; |
| |
| external int get hashCode; |
| |
| external toString(); |
| |
| /// Platform-private accessor which cannot be called from user libraries. |
| static String getName(Symbol symbol) => symbol._name; |
| |
| static String validatePublicSymbol(String name) { |
| if (name.isEmpty || publicSymbolPattern.hasMatch(name)) return name; |
| if (name.startsWith('_')) { |
| // There may be other private parts in a qualified name than the first |
| // one, but this is a common case that deserves a specific error |
| // message. |
| throw new ArgumentError('"$name" is a private identifier'); |
| } |
| throw new ArgumentError('"$name" is not a valid (qualified) symbol name'); |
| } |
| |
| /** |
| * Checks whether name is a valid symbol name. |
| * |
| * This test allows both private and non-private symbols. |
| */ |
| static bool isValidSymbol(String name) { |
| return (name.isEmpty || symbolPattern.hasMatch(name)); |
| } |
| |
| external static String computeUnmangledName(Symbol symbol); |
| } |