blob: ded3353291383475d8750f3b3dff07e5a4243065 [file] [log] [blame]
part of petitparser;
/**
* A token represents a parsed part of the input stream.
*
* The token holds the resulting value of the input, the input buffer,
* and the start and stop position in the input buffer. It provides many
* convenience methods to access the state of the token.
*/
class Token {
/**
* The parsed value of the token.
*/
final value;
/**
* The parsed buffer of the token.
*/
final buffer;
/**
* The start position of the token in the buffer.
*/
final int start;
/**
* The stop position of the token in the buffer.
*/
final int stop;
/**
* Constructs a token from the parsed value, the input buffer, and the
* start and stop position in the input buffer.
*/
const Token(this.value, this.buffer, this.start, this.stop);
/**
* The consumed input of the token.
*/
get input => buffer is String
? buffer.substring(start, stop)
: buffer.sublist(start, stop);
/**
* The length of the token.
*/
int get length => stop - start;
/**
* The line number of the token (only works for [String] buffers).
*/
int get line => Token.lineAndColumnOf(buffer, start)[0];
/**
* The column number of this token (only works for [String] buffers).
*/
int get column => Token.lineAndColumnOf(buffer, start)[1];
@override
String toString() => 'Token[${positionString(buffer, start)}]: $value';
@override
bool operator ==(other) {
return other is Token &&
value == other.value &&
start == other.start &&
stop == other.stop;
}
@override
int get hashCode => value.hashCode + start.hashCode + stop.hashCode;
static final Parser _NEWLINE_PARSER =
char('\n').or(char('\r').seq(char('\n').optional()));
/**
* Returns a parser for that detects newlines platform independently.
*/
static Parser newlineParser() => _NEWLINE_PARSER;
/**
* Converts the [position] index in a [buffer] to a line and column tuple.
*/
static List<int> lineAndColumnOf(String buffer, int position) {
var line = 1,
offset = 0;
for (var token in newlineParser().token().matchesSkipping(buffer)) {
if (position < token.stop) {
return [line, position - offset + 1];
}
line++;
offset = token.stop;
}
return [line, position - offset + 1];
}
/**
* Returns a human readable string representing the [position] index in a [buffer].
*/
static String positionString(buffer, int position) {
if (buffer is String) {
var lineAndColumn = Token.lineAndColumnOf(buffer, position);
return '${lineAndColumn[0]}:${lineAndColumn[1]}';
} else {
return '${position}';
}
}
}