GDB MI output parser

This commit is contained in:
Vadim Lopatin 2015-12-15 20:25:23 +03:00
parent 8c3a284d90
commit 820c88847c
1 changed files with 110 additions and 32 deletions

View File

@ -650,33 +650,75 @@ MIToken[] tokenizeMI(string s, out bool error) {
} }
MIValue parseMI(string s) { MIValue parseMI(string s) {
bool err = false; string src = s;
MIToken[] tokens = tokenizeMI(s, err); try {
if (error) { bool err = false;
// tokenizer error MIToken[] tokens = tokenizeMI(s, err);
return new MIValue(MIValueType.empty); if (err) {
// tokenizer error
return null;
}
MIValue[] items = parseMIList(tokens);
return new MIList(items);
} catch (Exception e) {
Log.e("Cannot parse MI from " ~ src, e);
return null;
} }
MIValue[] items = parseMI(tokens);
return new MIList(items);
} }
MIValue[] parseMI(MIToken[] tokens) { MIValue parseMIValue(ref MIToken[] tokens) {
MIValue[] res;
if (tokens.length == 0) if (tokens.length == 0)
return res; return null;
MITokenType tokenType = tokens.length > 0 ? tokens[0].type : MITokenType.eol; MITokenType tokenType = tokens.length > 0 ? tokens[0].type : MITokenType.eol;
MITokenType nextTokenType = tokens.length > 1 ? tokens[1].type : MITokenType.eol; MITokenType nextTokenType = tokens.length > 1 ? tokens[1].type : MITokenType.eol;
if (tokenType = MITokenType.ident) { if (tokenType == MITokenType.ident) {
string ident = tokens[0].str; string ident = tokens[0].str;
if (nextTokenType == MITokenType.eol || nextTokenType == MITokenType.comma) { if (nextTokenType == MITokenType.eol || nextTokenType == MITokenType.comma) {
res ~= new MIIdent(ident); MIValue res = new MIIdent(ident);
tokens = tokens[1..$]; tokens = tokens[1..$];
if (nextTokenType == MITokenType.comma) return res;
tokens = tokens[1..$];
} else if (nextTokenType == MITokenType.eq) { } else if (nextTokenType == MITokenType.eq) {
tokens = tokens[1..$];
MIValue value = parseMIValue(tokens);
MIValue res = new MIKeyValue(ident, value);
return res;
} }
throw new Exception("Unexpected token " ~ to!string(tokenType));
} else if (tokenType == MITokenType.str) {
string str = tokens[0].str;
tokens = tokens[1..$];
MIValue res = new MIString(str);
} else if (tokenType == MITokenType.curlyOpen) {
tokens = tokens[1..$];
MIValue[] list = parseMIList(tokens, MITokenType.curlyClose);
return new MIMap(list);
} else if (tokenType == MITokenType.squareOpen) {
tokens = tokens[1..$];
MIValue[] list = parseMIList(tokens, MITokenType.squareClose);
return new MIList(list);
}
throw new Exception("Invalid token at end of list: " ~ tokenType.to!string);
}
MIValue[] parseMIList(ref MIToken[] tokens, MITokenType closingToken = MITokenType.eol) {
MIValue[] res;
for (;;) {
MITokenType tokenType = tokens.length > 0 ? tokens[0].type : MITokenType.eol;
if (tokenType == MITokenType.eol)
return res;
if (tokenType == closingToken) {
tokens = tokens[1..$];
return res;
}
MIValue value = parseMIValue(tokens);
res ~= value;
tokenType = tokens.length > 0 ? tokens[0].type : MITokenType.eol;
if (tokenType == MITokenType.comma) {
tokens = tokens[1..$];
continue;
}
throw new Exception("Unexpected token in list " ~ to!string(tokenType));
} }
return res;
} }
enum MIValueType { enum MIValueType {
@ -700,43 +742,79 @@ class MIValue {
this.type = type; this.type = type;
} }
@property string str() { return null; } @property string str() { return null; }
@property int length() { return 1; }
MIValue opIndex(int index) { return null; }
MIValue opIndex(string key) { return null; }
} }
class MIKeyValue { class MIKeyValue : MIValue {
string key; private string _key;
MIValue value; private MIValue _value;
this(string key, MIValue value) { this(string key, MIValue value) {
super(MIValueType.keyValue); super(MIValueType.keyValue);
this.key = key; _key = key;
this.value = value; _value = value;
} }
@property string key() { return _key; }
@property string str() { return _key; }
@property MIValue value() { return _value; }
} }
class MIIdent { class MIIdent : MIValue {
string ident; private string _ident;
this(string ident) { this(string ident) {
super(MIValueType.ident); super(MIValueType.ident);
this.ident = ident; _ident = ident;
} }
override @property string str() { return ident; } override @property string str() { return _ident; }
} }
class MIString { class MIString : MIValue {
string str; private string _str;
this(string str) { this(string str) {
super(MIValueType.str); super(MIValueType.str);
this.str = str; _str = str;
} }
override @property string str() { return str; } override @property string str() { return _str; }
} }
class MIList { class MIList : MIValue {
MIValue[] items; private MIValue[] _items;
private MIValue[string] _map;
override @property int length() { return cast(int)_items.length; }
override MIValue opIndex(int index) {
if (index < 0 || index >= _items.length)
return null;
return _items[index];
}
override MIValue opIndex(string key) {
if (key in _map) {
MIValue res = _map[key];
return res;
}
return null;
}
this(MIValue[] items) { this(MIValue[] items) {
super(MIValueType.list); super(MIValueType.list);
this.items = items; _items = items;
// fill map
foreach(item; _items) {
if (item.type == MIValueType.keyValue) {
if (!item.str.empty)
_map[item.str] = (cast(MIKeyValue)item).value;
}
}
}
}
class MIMap : MIList {
this(MIValue[] items) {
super(items);
type = MIValueType.map;
} }
override @property string str() { return str; }
} }
private char nextChar(ref string s) { private char nextChar(ref string s) {