Index: lib/src/line_scanner.dart |
diff --git a/lib/src/line_scanner.dart b/lib/src/line_scanner.dart |
index 54ecf7bf9e62215d7a7412a760a24fb1b5dae60d..148ad6081395cae8de857049ba55400324ca30ca 100644 |
--- a/lib/src/line_scanner.dart |
+++ b/lib/src/line_scanner.dart |
@@ -4,8 +4,13 @@ |
library string_scanner.line_scanner; |
+import 'package:charcode/ascii.dart'; |
+ |
import 'string_scanner.dart'; |
+/// A regular expression matching newlines across platforms. |
+final _newlineRegExp = new RegExp(r"\r\n?|\n"); |
+ |
/// A subclass of [StringScanner] that tracks line and column information. |
class LineScanner extends StringScanner { |
/// The scanner's current (zero-based) line number. |
@@ -24,6 +29,10 @@ class LineScanner extends StringScanner { |
LineScannerState get state => |
new LineScannerState._(this, position, line, column); |
+ /// Whether the current position is between a CR character and an LF |
+ /// charactet. |
+ bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; |
+ |
set state(LineScannerState state) { |
if (!identical(state._scanner, this)) { |
throw new ArgumentError("The given LineScannerState was not returned by " |
@@ -40,8 +49,10 @@ class LineScanner extends StringScanner { |
super.position = newPosition; |
if (newPosition > oldPosition) { |
- var newlines = |
- "\n".allMatches(string.substring(oldPosition, newPosition)).toList(); |
+ var newlines = _newlineRegExp |
+ .allMatches(string.substring(oldPosition, newPosition)).toList(); |
+ if (_betweenCRLF) newlines.removeLast(); |
Bob Nystrom
2015/09/02 00:07:24
How about hoisting this to a function:
int _newli
nweiz
2015/09/02 00:10:57
Done.
|
+ |
_line += newlines.length; |
if (newlines.isEmpty) { |
_column += newPosition - oldPosition; |
@@ -49,13 +60,16 @@ class LineScanner extends StringScanner { |
_column = newPosition - newlines.last.end; |
} |
} else { |
- var newlines = |
- "\n".allMatches(string.substring(newPosition, oldPosition)).toList(); |
+ var newlines = _newlineRegExp |
+ .allMatches(string.substring(newPosition, oldPosition)).toList(); |
+ if (_betweenCRLF) newlines.removeLast(); |
+ |
_line -= newlines.length; |
if (newlines.isEmpty) { |
_column -= oldPosition - newPosition; |
} else { |
- _column = newPosition - string.lastIndexOf("\n", newPosition) - 1; |
+ _column = newPosition - |
+ string.lastIndexOf(_newlineRegExp, newPosition) - 1; |
} |
} |
} |
@@ -65,7 +79,7 @@ class LineScanner extends StringScanner { |
int readChar() { |
var char = super.readChar(); |
- if (char == 0xA) { |
+ if (char == $lf || (char == $cr && peekChar() != $lf)) { |
_line += 1; |
_column = 0; |
} else { |
@@ -77,7 +91,8 @@ class LineScanner extends StringScanner { |
bool scan(Pattern pattern) { |
if (!super.scan(pattern)) return false; |
- var newlines = "\n".allMatches(lastMatch[0]).toList(); |
+ var newlines = _newlineRegExp.allMatches(lastMatch[0]).toList(); |
+ if (_betweenCRLF) newlines.removeLast(); |
_line += newlines.length; |
Bob Nystrom
2015/09/02 00:07:24
Even here.
nweiz
2015/09/02 00:10:57
Done.
|
if (newlines.isEmpty) { |
_column += lastMatch[0].length; |