OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
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 part of dart._internal; | |
6 | |
7 /** | |
8 * Implementation of [core.Symbol]. This class uses the same name as | |
9 * a core class so a user can't tell the difference. | |
10 * | |
11 * The purpose of this class is to hide [_name] from user code, but | |
12 * make it accessible to Dart platform code via the static method | |
13 * [getName]. | |
14 */ | |
15 class Symbol implements core.Symbol { | |
16 final String _name; | |
17 | |
18 // Used internally by DDC to map ES6 symbols to Dart. | |
19 final dynamic _nativeSymbol; | |
20 | |
21 /** | |
22 * Source of RegExp matching Dart reserved words. | |
23 * | |
24 * Reserved words are not allowed as identifiers. | |
25 */ | |
26 static const String reservedWordRE = | |
27 r'(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|' | |
28 r'e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|' | |
29 r'ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|' | |
30 r'v(?:ar|oid)|w(?:hile|ith))'; | |
31 /** | |
32 * Source of RegExp matching any public identifier. | |
33 * | |
34 * A public identifier is a valid identifier (not a reserved word) | |
35 * that doesn't start with '_'. | |
36 */ | |
37 static const String publicIdentifierRE = | |
38 r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$][\w$]*'; | |
39 /** | |
40 * Source of RegExp matching any identifier. | |
41 * | |
42 * It matches identifiers but not reserved words. The identifiers | |
43 * may start with '_'. | |
44 */ | |
45 static const String identifierRE = | |
46 r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$_][\w$]*'; | |
47 /** | |
48 * Source of RegExp matching a declarable operator names. | |
49 * | |
50 * The operators that can be declared using `operator` declarations are | |
51 * also the only ones allowed as symbols. The name of the oeprators is | |
52 * the same as the operator itself except for unary minus, where the name | |
53 * is "unary-". | |
54 */ | |
55 static const String operatorRE = | |
56 r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>[>=]?|unary-)'; | |
57 | |
58 // Grammar if symbols: | |
59 // symbol ::= qualifiedName | <empty> | |
60 // qualifiedName ::= publicIdentifier '.' qualifiedName | name | |
61 // name ::= publicIdentifier | |
62 // | publicIdentifier '=' | |
63 // | operator | |
64 // where publicIdentifier is any valid identifier (not a reserved word) | |
65 // that isn't private (doesn't start with '_'). | |
66 // | |
67 // Railroad diagram of the accepted grammar: | |
68 // | |
69 // /----------------\ | |
70 // | | | |
71 // | /-[.]-/ /-[=]-\ | |
72 // \ / / \ | |
73 // -------[id]-------------------------> | |
74 // \ / | |
75 // \------[operator]---/ | |
76 // \ / | |
77 // \------------/ | |
78 // | |
79 | |
80 /** | |
81 * RegExp that validates a non-empty non-private symbol. | |
82 * | |
83 * The empty symbol is handled before this regexp is used, and is not | |
84 * accepted. | |
85 */ | |
86 static final RegExp publicSymbolPattern = new RegExp( | |
87 '^(?:$operatorRE\$|$publicIdentifierRE(?:=?\$|[.](?!\$)))+?\$'); | |
88 | |
89 // The grammar of symbols that may be private is the same as for public | |
90 // symbols, except that "publicIdentifier" is replaced by "identifier", | |
91 // which matches any identifier. | |
92 | |
93 /** | |
94 * RegExp that validates a non-empty symbol. | |
95 * | |
96 * Private symbols are accepted. | |
97 * | |
98 * The empty symbol is handled before this regexp is used, and is not | |
99 * accepted. | |
100 */ | |
101 static final RegExp symbolPattern = | |
102 new RegExp('^(?:$operatorRE\$|$identifierRE(?:=?\$|[.](?!\$)))+?\$'); | |
103 | |
104 external const Symbol(String name); | |
105 | |
106 external const Symbol.es6(String name, nativeSymbol); | |
107 | |
108 /** | |
109 * Platform-private method used by the mirror system to create | |
110 * otherwise invalid names. | |
111 */ | |
112 const Symbol.unvalidated(this._name) : this._nativeSymbol = null; | |
113 | |
114 // This is called by dart2js. | |
115 Symbol.validated(String name) | |
116 : this._name = validatePublicSymbol(name), | |
117 this._nativeSymbol = null; | |
118 | |
119 bool operator ==(Object other) => | |
120 other is Symbol && | |
121 _name == other._name && | |
122 _nativeSymbol == other._nativeSymbol; | |
123 | |
124 external int get hashCode; | |
125 | |
126 toString() => 'Symbol("$_name")'; | |
127 | |
128 /// Platform-private accessor which cannot be called from user libraries. | |
129 static String getName(Symbol symbol) => symbol._name; | |
130 | |
131 static dynamic getNativeSymbol(Symbol symbol) => symbol._nativeSymbol; | |
132 | |
133 static String validatePublicSymbol(String name) { | |
134 if (name.isEmpty || publicSymbolPattern.hasMatch(name)) return name; | |
135 if (name.startsWith('_')) { | |
136 // There may be other private parts in a qualified name than the first | |
137 // one, but this is a common case that deserves a specific error | |
138 // message. | |
139 throw new ArgumentError('"$name" is a private identifier'); | |
140 } | |
141 throw new ArgumentError('"$name" is not a valid (qualified) symbol name'); | |
142 } | |
143 | |
144 /** | |
145 * Checks whether name is a valid symbol name. | |
146 * | |
147 * This test allows both private and non-private symbols. | |
148 */ | |
149 static bool isValidSymbol(String name) { | |
150 return (name.isEmpty || symbolPattern.hasMatch(name)); | |
151 } | |
152 } | |
OLD | NEW |