Chromium Code Reviews

Side by Side Diff: pkg/mustache/lib/scanner.dart

Issue 804973002: Add appengine/gcloud/mustache dependencies. (Closed) Base URL: git@github.com:dart-lang/pub-dartlang-dart.git@master
Patch Set: Added AUTHORS/LICENSE/PATENTS files Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « pkg/mustache/lib/mustache.dart ('k') | pkg/mustache/lib/template.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 part of mustache;
2
3 //FIXME Temporarily made public for testing.
4 //List<_Token> scan(String source, bool lenient) => _scan(source, lenient);
5 //List<_Token> trim(List<_Token> tokens) => _trim(tokens);
6
7 List<_Token> _scan(String source, bool lenient) => _trim(new _Scanner(source).sc an());
8
9 const int _TEXT = 1;
10 const int _VARIABLE = 2;
11 const int _PARTIAL = 3;
12 const int _OPEN_SECTION = 4;
13 const int _OPEN_INV_SECTION = 5;
14 const int _CLOSE_SECTION = 6;
15 const int _COMMENT = 7;
16 const int _UNESC_VARIABLE = 8;
17 const int _WHITESPACE = 9; // Should be filtered out, before returned by scan.
18 const int _LINE_END = 10; // Should be filtered out, before returned by scan.
19
20 //FIXME make private
21 tokenTypeString(int type) => [
22 '?',
23 'Text',
24 'Var',
25 'Par',
26 'Open',
27 'OpenInv',
28 'Close',
29 'Comment',
30 'UnescVar',
31 'Whitespace',
32 'LineEnd'][type];
33
34 const int _EOF = -1;
35 const int _TAB = 9;
36 const int _NEWLINE = 10;
37 const int _RETURN = 13;
38 const int _SPACE = 32;
39 const int _EXCLAIM = 33;
40 const int _QUOTE = 34;
41 const int _APOS = 39;
42 const int _HASH = 35;
43 const int _AMP = 38;
44 const int _PERIOD = 46;
45 const int _FORWARD_SLASH = 47;
46 const int _LT = 60;
47 const int _GT = 62;
48 const int _CARET = 94;
49
50 const int _OPEN_MUSTACHE = 123;
51 const int _CLOSE_MUSTACHE = 125;
52
53 // Takes a list of tokens, and removes _NEWLINE, and _WHITESPACE tokens.
54 // This is used to implement mustache standalone lines.
55 // Where TAG is one of: OPEN_SECTION, INV_SECTION, CLOSE_SECTION
56 // LINE_END, [WHITESPACE], TAG, [WHITESPACE], LINE_END => LINE_END, TAG
57 // WHITESPACE => TEXT
58 // LINE_END => TEXT
59 //TODO Consecutive text tokens will also be merged into a single token. (Do in a separate merge func).
60 List<_Token> _trim(List<_Token> tokens) {
61 int i = 0;
62 _Token read() { var ret = i < tokens.length ? tokens[i++] : null; /* pri nt('Read: $ret'); */ return ret; }
63 _Token peek([int n = 0]) => i + n < tokens.length ? tokens[i + n] : null ;
64
65 bool isTag(token) =>
66 token != null
67 && (token.type == _OPEN_SECTION
68 || token.type == _OPEN_INV_SECTION
69 || token.type == _CLOSE_SECTION
70 || token.type == _COMMENT);
71
72 bool isWhitespace(token) => token != null && token.type == _WHITESPACE;
73 bool isLineEnd(token) => token != null && token.type == _LINE_END;
74
75 var result = new List<_Token>();
76 add(token) => result.add(token);
77
78 standaloneLineCheck() {
79 // Swallow leading whitespace
80 // Note, the scanner will only ever create a single whitespace t oken. There
81 // is no need to handle multiple whitespace tokens.
82 if (isWhitespace(peek())
83 && isTag(peek(1))
84 && (isLineEnd(peek(2)) || peek(2) == null)) { // null == EOF
85 read();
86 } else if (isWhitespace(peek())
87 && isTag(peek(1))
88 && isWhitespace(peek(2))
89 && (isLineEnd(peek(3)) || peek(3) == null)) {
90 read();
91 }
92
93 if ((isTag(peek()) && isLineEnd(peek(1)))
94 || (isTag(peek())
95 && isWhitespace(peek(1))
96 && (isLineEnd(peek(2)) || peek(2) == null))) {
97
98 // Add tag
99 add(read());
100
101 // Swallow trailing whitespace.
102 if (isWhitespace(peek()))
103 read();
104
105 // Swallow line end.
106 assert(isLineEnd(peek()));
107 read();
108
109 standaloneLineCheck(); //FIXME don't use recursion.
110 }
111 }
112
113 // Handle case where first line is a standalone tag.
114 standaloneLineCheck();
115
116 var t;
117 while ((t = read()) != null) {
118 if (t.type == _LINE_END) {
119 // Convert line end to text token
120 add(new _Token(_TEXT, t.value, t.line, t.column));
121 standaloneLineCheck();
122 } else if (t.type == _WHITESPACE) {
123 // Convert whitespace to text token
124 add(new _Token(_TEXT, t.value, t.line, t.column));
125 } else {
126 // Preserve token
127 add(t);
128 }
129 }
130
131 return result;
132 }
133
134 class _Token {
135 _Token(this.type, this.value, this.line, this.column);
136 final int type;
137 final String value;
138 final int line;
139 final int column;
140 toString() => "${tokenTypeString(type)}: \"${value.replaceAll('\n', '\\n ')}\" $line:$column";
141 }
142
143 class _Scanner {
144 _Scanner(String source) : _r = new _CharReader(source);
145
146 _CharReader _r;
147 List<_Token> _tokens = new List<_Token>();
148
149 int _read() => _r.read();
150 int _peek() => _r.peek();
151
152 _addStringToken(int type) {
153 int l = _r.line, c = _r.column;
154 var value = type == _TEXT ? _readLine() : _readString();
155 if (type != _TEXT && type != _COMMENT) value = value.trim();
156 _tokens.add(new _Token(type, value, l, c));
157 }
158
159 _addCharToken(int type, int charCode) {
160 int l = _r.line, c = _r.column;
161 var value = new String.fromCharCode(charCode);
162 _tokens.add(new _Token(type, value, l, c));
163 }
164
165 _expect(int expectedCharCode) {
166 int c = _read();
167
168 if (c == _EOF) {
169 throw new MustacheFormatException('Unexpected end of inp ut.', _r.line, _r.column);
170
171 } else if (c != expectedCharCode) {
172 throw new MustacheFormatException('Unexpected character, '
173 'expected: ${new String.fromCharCode(expectedCha rCode)} ($expectedCharCode), '
174 'was: ${new String.fromCharCode(c)} ($c), '
175 'at: ${_r.line}:${_r.column}', _r.line, _r.colum n);
176 }
177 }
178
179 String _readString() => _r.readWhile(
180 (c) => c != _OPEN_MUSTACHE
181 && c != _CLOSE_MUSTACHE
182 && c != _EOF);
183
184 String _readLine() => _r.readWhile(
185 (c) => c != _OPEN_MUSTACHE
186 && c != _CLOSE_MUSTACHE
187 && c != _EOF
188 && c != _NEWLINE);
189
190 // Actually excludes newlines.
191 String _readWhitespace() => _r.readWhile(
192 (c) => c == _SPACE
193 || c == _TAB);
194
195 List<_Token> scan() {
196 while(true) {
197 switch(_peek()) {
198 case _EOF:
199 return _tokens;
200 case _OPEN_MUSTACHE:
201 _scanMustacheTag();
202 break;
203 default:
204 _scanText();
205 }
206 }
207 }
208
209 _scanText() {
210 while(true) {
211 switch(_peek()) {
212 case _EOF:
213 return;
214 case _OPEN_MUSTACHE:
215 return;
216 case _CLOSE_MUSTACHE:
217 _read();
218 _addCharToken(_TEXT, _CLOSE_MUSTACHE);
219 break;
220 case _RETURN:
221 _read();
222 if (_peek() == _NEWLINE) {
223 _read();
224 _tokens.add(new _Token(_LINE_END , '\r\n', _r.line, _r.column));
225 } else {
226 _addCharToken(_TEXT, _RETURN);
227 }
228 break;
229 case _NEWLINE:
230 _read();
231 _addCharToken(_LINE_END, _NEWLINE); //TO DO handle \r\n
232 break;
233 case _SPACE:
234 case _TAB:
235 var value = _readWhitespace();
236 _tokens.add(new _Token(_WHITESPACE, valu e, _r.line, _r.column));
237 break;
238 default:
239 _addStringToken(_TEXT);
240 }
241 }
242 }
243
244 _scanMustacheTag() {
245 _expect(_OPEN_MUSTACHE);
246
247 // If just a single mustache, return this as a text token.
248 if (_peek() != _OPEN_MUSTACHE) {
249 _addCharToken(_TEXT, _OPEN_MUSTACHE);
250 return;
251 }
252
253 _expect(_OPEN_MUSTACHE);
254
255 switch(_peek()) {
256 case _EOF:
257 throw new MustacheFormatException('Unexpected en d of input.', _r.line, _r.column);
258
259 // Escaped text {{{ ... }}}
260 case _OPEN_MUSTACHE:
261 _read();
262 _addStringToken(_UNESC_VARIABLE);
263 _expect(_CLOSE_MUSTACHE);
264 break;
265
266 // Escaped text {{& ... }}
267 case _AMP:
268 _read();
269 _addStringToken(_UNESC_VARIABLE);
270 break;
271
272 // Comment {{! ... }}
273 case _EXCLAIM:
274 _read();
275 _addStringToken(_COMMENT);
276 break;
277
278 // Partial {{> ... }}
279 case _GT:
280 _read();
281 _addStringToken(_PARTIAL);
282 break;
283
284 // Open section {{# ... }}
285 case _HASH:
286 _read();
287 _addStringToken(_OPEN_SECTION);
288 break;
289
290 // Open inverted section {{^ ... }}
291 case _CARET:
292 _read();
293 _addStringToken(_OPEN_INV_SECTION);
294 break;
295
296 // Close section {{/ ... }}
297 case _FORWARD_SLASH:
298 _read();
299 _addStringToken(_CLOSE_SECTION);
300 break;
301
302 // Variable {{ ... }}
303 default:
304 _addStringToken(_VARIABLE);
305 }
306
307 _expect(_CLOSE_MUSTACHE);
308 _expect(_CLOSE_MUSTACHE);
309 }
310 }
311
OLDNEW
« no previous file with comments | « pkg/mustache/lib/mustache.dart ('k') | pkg/mustache/lib/template.dart » ('j') | no next file with comments »

Powered by Google App Engine