Files
sdk/pkg/vm_service/tool/common/parser.dart
T
Ben Konyi 368b3f0ab4 Reland "[ VM / Service ] Pulled in vm_service_drivers from its own repo."
Changes from original CL:
 * Removed service_undocumented.md
 * Removed generation of wrappers for undocumented RPCs
 * Cleaned up generation code which was used for generating wrappers for undocumented RPCs
 * Removed JARs from pkg/vm_service/java/third_party

This reverts commit 477a3c4748.

Change-Id: I8d36733c8b2602e4935c3f23698d3f7c97a20187
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/110135
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
2019-07-25 18:46:43 +00:00

173 lines
3.5 KiB
Dart

// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library parser;
class Token {
static final RegExp _alpha = new RegExp(r'^[0-9a-zA-Z_\-@]+$');
final String text;
Token next;
Token(this.text);
bool get eof => text == null;
bool get isName {
if (text == null || text.isEmpty) return false;
return _alpha.hasMatch(text);
}
bool get isComment => text != null && text.startsWith('//');
String toString() => text == null ? 'EOF' : text;
}
class Tokenizer {
static final alphaNum =
'@abcdefghijklmnopqrstuvwxyz-_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
static final whitespace = ' \n\t\r';
String text;
Token _head;
Token _last;
Tokenizer(this.text);
Token tokenize() {
_emit(null);
for (int i = 0; i < text.length; i++) {
String c = text[i];
if (whitespace.contains(c)) {
// skip
} else if (c == '/' && _peek(i) == '/') {
int index = text.indexOf('\n', i);
if (index == -1) index = text.length;
_emit(text.substring(i, index));
i = index;
} else if (alphaNum.contains(c)) {
int start = i;
while (alphaNum.contains(_peek(i))) {
i++;
}
_emit(text.substring(start, i + 1));
} else {
_emit(c);
}
}
_emit(null);
_head = _head.next;
return _head;
}
void _emit(String value) {
Token token = new Token(value);
if (_head == null) _head = token;
if (_last != null) _last.next = token;
_last = token;
}
String _peek(int i) {
i += 1;
return i < text.length ? text[i] : new String.fromCharCodes([0]);
}
String toString() {
StringBuffer buf = new StringBuffer();
Token t = _head;
buf.write('[${t}]\n');
while (!t.eof) {
t = t.next;
buf.write('[${t}]\n');
}
return buf.toString().trim();
}
}
abstract class Parser {
final Token startToken;
Token current;
Parser(this.startToken);
Token expect(String text) {
Token t = advance();
if (text != t.text) fail('expected ${text}, got ${t}');
return t;
}
bool consume(String text) {
if (peek().text == text) {
advance();
return true;
} else {
return false;
}
}
Token peek() =>
current == null ? startToken : current.eof ? current : current.next;
Token expectName() {
Token t = advance();
if (!t.isName) fail('expected name token, got ${t}');
return t;
}
Token advance() {
if (current == null) {
current = startToken;
} else if (!current.eof) {
current = current.next;
}
return current;
}
String collectComments() {
StringBuffer buf = new StringBuffer();
while (peek().isComment) {
Token t = advance();
String str = t.text.substring(2);
if (str.startsWith(' ')) str = str.substring(1);
if (str.startsWith(' ')) {
buf.write('\n - ${str.substring(2)}');
} else if (str.isEmpty) {
buf.write('\n\n');
} else {
buf.write('${str} ');
}
}
if (buf.isEmpty) return null;
return buf
.toString()
.split('\n')
.map((line) => line.trimRight())
.join('\n')
.trim();
}
void validate(bool result, String message) {
if (!result) throw 'expected ${message}';
}
void fail(String message) => throw message;
}