Remove char reader class, merge code into scanner
diff --git a/lib/mustache.dart b/lib/mustache.dart
index 94758e9..eab0f6c 100644
--- a/lib/mustache.dart
+++ b/lib/mustache.dart
@@ -3,7 +3,6 @@
@MirrorsUsed(metaTargets: const [mustache])
import 'dart:mirrors';
-part 'src/char_reader.dart';
part 'src/lambda_context.dart';
part 'src/node.dart';
part 'src/parse.dart';
diff --git a/lib/src/char_reader.dart b/lib/src/char_reader.dart
deleted file mode 100644
index c76a2d3..0000000
--- a/lib/src/char_reader.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-part of mustache;
-
-// TODO remove line and column. Not required anymore.
-class _CharReader {
-
- String _source;
- Iterator<int> _itr;
- int _i, _c;
- int _line = 1, _column = 1;
-
- _CharReader(String source)
- : _source = source,
- _itr = source.runes.iterator {
-
- if (source == null)
- throw new ArgumentError('Source is null.');
-
- _i = 0;
-
- if (source == '') {
- _c = _EOF;
- } else {
- _itr.moveNext();
- _c = _itr.current;
- }
- }
-
- int get line => _line;
- int get column => _column;
- int get offset => _i;
-
- int read() {
- var c = _c;
- if (_itr.moveNext()) {
- _i++;
- _c = _itr.current;
- } else {
- _c = _EOF;
- }
-
- if (c == _NEWLINE) {
- _line++;
- _column = 1;
- } else {
- _column++;
- }
-
- return c;
- }
-
- int peek() => _c;
-
- String readWhile(bool test(int charCode), [Function endOfFile]) {
-
- int start = _i;
-
- while (peek() != _EOF && test(peek())) {
- read();
- }
-
- if (peek() == _EOF && endOfFile != null) endOfFile();
-
- int end = peek() == _EOF ? _source.length : _i;
- return _source.substring(start, end);
- }
-}
\ No newline at end of file
diff --git a/lib/src/scanner.dart b/lib/src/scanner.dart
index 6967efd..ab800a6 100644
--- a/lib/src/scanner.dart
+++ b/lib/src/scanner.dart
@@ -3,23 +3,33 @@
class _Scanner {
_Scanner(String source, this._templateName, String delimiters, {bool lenient: true})
- : _r = new _CharReader(source),
- _source = source,
- _lenient = lenient {
+ : _source = source,
+ _lenient = lenient,
+ _itr = source.runes.iterator {
var delims = _parseDelimiterString(delimiters);
_openDelimiter = delims[0];
_openDelimiterInner = delims[1];
_closeDelimiterInner = delims[2];
_closeDelimiter = delims[3];
+
+ if (source == '') {
+ _c = _EOF;
+ } else {
+ _itr.moveNext();
+ _c = _itr.current;
+ }
}
final String _templateName;
final String _source;
final bool _lenient;
- _CharReader _r;
- List<_Token> _tokens = new List<_Token>();
+ final Iterator<int> _itr;
+ int _offset = 0;
+ int _c = 0;
+
+ final List<_Token> _tokens = new List<_Token>();
// These can be changed by the change delimiter tag.
int _openDelimiter;
@@ -37,21 +47,44 @@
return _tokens;
}
- int _read() => _r.read();
- int _peek() => _r.peek();
-
+ int _peek() => _c;
+
+ int _read() {
+ var c = _c;
+ if (_itr.moveNext()) {
+ _offset++;
+ _c = _itr.current;
+ } else {
+ _c = _EOF;
+ }
+ return c;
+ }
+
+ String _readWhile(bool test(int charCode), [Function endOfFile]) {
+
+ int start = _offset;
+ while (_peek() != _EOF && test(_peek())) {
+ _read();
+ }
+
+ if (_peek() == _EOF && endOfFile != null) endOfFile();
+
+ int end = _peek() == _EOF ? _source.length : _offset;
+ return _source.substring(start, end);
+ }
+
_expect(int expectedCharCode) {
int c = _read();
if (c == _EOF) {
throw new _TemplateException('Unexpected end of input',
- _templateName, _source, _r.offset);
+ _templateName, _source, _offset);
} else if (c != expectedCharCode) {
throw new _TemplateException('Unexpected character, '
'expected: ${new String.fromCharCode(expectedCharCode)} ($expectedCharCode), '
'was: ${new String.fromCharCode(c)} ($c)',
- _templateName, _source, _r.offset);
+ _templateName, _source, _offset);
}
}
@@ -76,7 +109,7 @@
while(true) {
int c = _peek();
- int start = _r.offset;
+ int start = _offset;
if (c == _EOF) {
return;
@@ -89,31 +122,31 @@
} else if (c == _NEWLINE) {
_read();
var value = new String.fromCharCode(c);
- _tokens.add(new _Token(_LINE_END, value, start, _r.offset));
+ _tokens.add(new _Token(_LINE_END, value, start, _offset));
} else if (c == _RETURN) {
_read();
if (_peek() == _NEWLINE) {
_read();
- _tokens.add(new _Token(_LINE_END, '\r\n', start, _r.offset));
+ _tokens.add(new _Token(_LINE_END, '\r\n', start, _offset));
} else {
var value = new String.fromCharCode(_RETURN);
- _tokens.add(new _Token(_TEXT, '\n', start, _r.offset));
+ _tokens.add(new _Token(_TEXT, '\n', start, _offset));
}
} else if (c == _SPACE || c == _TAB) {
- var value = _r.readWhile((c) => c == _SPACE || c == _TAB);
- _tokens.add(new _Token(_WHITESPACE, value, start, _r.offset));
+ var value = _readWhile((c) => c == _SPACE || c == _TAB);
+ _tokens.add(new _Token(_WHITESPACE, value, start, _offset));
} else {
- var value = _r.readWhile((c) => c != _openDelimiter && c != _NEWLINE);
- _tokens.add(new _Token(_TEXT, value, start, _r.offset));
+ var value = _readWhile((c) => c != _openDelimiter && c != _NEWLINE);
+ _tokens.add(new _Token(_TEXT, value, start, _offset));
}
}
}
void _scanMustacheTag() {
- int start = _r.offset;
+ int start = _offset;
int sigil = 0;
_expect(_openDelimiter);
@@ -121,7 +154,7 @@
// If just a single delimeter character then this is a text token.
if (_openDelimiterInner != null && _peek() != _openDelimiterInner) {
var value = new String.fromCharCode(_openDelimiter);
- _tokens.add(new _Token(_TEXT, value, start, _r.offset));
+ _tokens.add(new _Token(_TEXT, value, start, _offset));
return;
}
@@ -167,7 +200,7 @@
var type = sigils[sigil];
var indent = type == _PARTIAL ? _getPrecedingWhitespace() : '';
- _tokens.add(new _Token(type, identifier, start, _r.offset, indent: indent));
+ _tokens.add(new _Token(type, identifier, start, _offset, indent: indent));
}
_errorEofInTag() => throw _error('Tag not closed before the end of the template.');
@@ -175,9 +208,9 @@
_scanTagWhitespace() {
const whitepsace = const [_SPACE, _NEWLINE, _RETURN, _TAB];
if (_lenient) {
- _r.readWhile(_isWhitespace, _errorEofInTag);
+ _readWhile(_isWhitespace, _errorEofInTag);
} else {
- _r.readWhile((c) => c == _SPACE, _errorEofInTag);
+ _readWhile((c) => c == _SPACE, _errorEofInTag);
if (_isWhitespace(_peek()))
throw _error('Tags may not contain newlines or tabs.');
}
@@ -188,12 +221,12 @@
? _closeDelimiterInner
: _closeDelimiter;
if (_lenient) {
- return _r.readWhile(
+ return _readWhile(
(c) => c != delim
|| tripleMo && c != _CLOSE_MUSTACHE,
_errorEofInTag).trim();
} else {
- var id = _r.readWhile(_isAlphanum, _errorEofInTag);
+ var id = _readWhile(_isAlphanum, _errorEofInTag);
_scanTagWhitespace();
if (_peek() != delim) throw _error('Unless in lenient mode tags may only '
'contain the characters a-z, A-Z, minus, underscore and period.');
@@ -225,16 +258,16 @@
_expect(_CLOSE_MUSTACHE);
if (_closeDelimiterInner != null) _expect(_closeDelimiterInner);
_expect(_closeDelimiter);
- _tokens.add(new _Token(_UNESC_VARIABLE, value, start, _r.offset));
+ _tokens.add(new _Token(_UNESC_VARIABLE, value, start, _offset));
}
void _scanCommentTag(int start) {
var value = _closeDelimiterInner != null
- ? _r.readWhile((c) => c != _closeDelimiterInner, _errorEofInTag).trim()
- : _r.readWhile((c) => c != _closeDelimiter, _errorEofInTag).trim();
+ ? _readWhile((c) => c != _closeDelimiterInner, _errorEofInTag).trim()
+ : _readWhile((c) => c != _closeDelimiter, _errorEofInTag).trim();
if (_closeDelimiterInner != null) _expect(_closeDelimiterInner);
_expect(_closeDelimiter);
- _tokens.add(new _Token(_COMMENT, value, start, _r.offset));
+ _tokens.add(new _Token(_COMMENT, value, start, _offset));
}
//TODO consider changing the parsing here to use a regexp. It will probably
@@ -248,12 +281,12 @@
_scanTagWhitespace();
int c;
- c = _r.read();
+ c = _read();
if (c == _EQUAL) throw _error('Incorrect change delimiter tag.');
_openDelimiter = c;
- c = _r.read();
+ c = _read();
if (_isWhitespace(c)) {
_openDelimiterInner = null;
} else {
@@ -262,7 +295,7 @@
_scanTagWhitespace();
- c = _r.read();
+ c = _read();
if (_isWhitespace(c) || c == _EQUAL)
throw _error('Incorrect change delimiter tag.');
@@ -288,11 +321,11 @@
_closeDelimiterInner,
_closeDelimiter);
- _tokens.add(new _Token(_CHANGE_DELIMITER, value, start, _r.offset));
+ _tokens.add(new _Token(_CHANGE_DELIMITER, value, start, _offset));
}
TemplateException _error(String message) {
- return new _TemplateException(message, _templateName, _source, _r.offset);
+ return new _TemplateException(message, _templateName, _source, _offset);
}
}