Debugger: Implement member dereferencing in expressions.
CLanguageExpressionEvaluator: - Add tokenizer handling for operators . and ->. - Rework _ParseIdentifier() to work recursively if it sees a deref operator immediately following the current token. This allows one to refer to the value of structure/class members in an expression.
This commit is contained in:
parent
824404e31f
commit
5cd3ae7c0d
@ -58,7 +58,9 @@ enum {
|
||||
TOKEN_GT,
|
||||
TOKEN_GE,
|
||||
TOKEN_LT,
|
||||
TOKEN_LE
|
||||
TOKEN_LE,
|
||||
|
||||
TOKEN_MEMBER_PTR
|
||||
};
|
||||
|
||||
static BString TokenTypeToString(int32 type)
|
||||
@ -150,6 +152,10 @@ static BString TokenTypeToString(int32 type)
|
||||
token = "<=";
|
||||
break;
|
||||
|
||||
case TOKEN_MEMBER_PTR:
|
||||
token = "->";
|
||||
break;
|
||||
|
||||
default:
|
||||
token.SetToFormat("Unknown token type %" B_PRId32, type);
|
||||
break;
|
||||
@ -295,6 +301,17 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
||||
}
|
||||
|
||||
int32 length = fCurrentChar - begin;
|
||||
if (length == 1 && decimal) {
|
||||
// check for . operator
|
||||
fCurrentChar = begin;
|
||||
if (!_ParseOperator()) {
|
||||
throw ParseException("unexpected character",
|
||||
_CurrentPos());
|
||||
}
|
||||
|
||||
return fCurrentToken;
|
||||
}
|
||||
|
||||
BString test = temp;
|
||||
test << "&_";
|
||||
double value;
|
||||
@ -361,16 +378,20 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
||||
break;
|
||||
|
||||
case '-':
|
||||
type = TOKEN_MINUS;
|
||||
length = 1;
|
||||
if (Peek() == '>') {
|
||||
type = TOKEN_MEMBER_PTR;
|
||||
length = 2;
|
||||
} else {
|
||||
type = TOKEN_MINUS;
|
||||
length = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if (Peek() == '*') {
|
||||
type = TOKEN_POWER;
|
||||
length = 2;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
type = TOKEN_STAR;
|
||||
length = 1;
|
||||
}
|
||||
@ -453,6 +474,11 @@ class CLanguageExpressionEvaluator::Tokenizer {
|
||||
length = 1;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
type = TOKEN_MEMBER_PTR;
|
||||
length = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -764,7 +790,7 @@ CLanguageExpressionEvaluator::_ParseUnary()
|
||||
|
||||
|
||||
Number
|
||||
CLanguageExpressionEvaluator::_ParseIdentifier()
|
||||
CLanguageExpressionEvaluator::_ParseIdentifier(ValueNode* parentNode)
|
||||
{
|
||||
Token token = fTokenizer->NextToken();
|
||||
Number value;
|
||||
@ -780,34 +806,41 @@ CLanguageExpressionEvaluator::_ParseIdentifier()
|
||||
AutoLocker<ValueNodeContainer> containerLocker(container);
|
||||
|
||||
ValueNodeChild* child = NULL;
|
||||
ValueNodeChild* thisChild = NULL;
|
||||
for (int32 i = 0; i < container->CountChildren(); i++) {
|
||||
ValueNodeChild* current = container->ChildAt(i);
|
||||
const BString& nodeName = current->Name();
|
||||
if (nodeName == identifierName) {
|
||||
child = current;
|
||||
break;
|
||||
} else if (nodeName == "this")
|
||||
thisChild = current;
|
||||
}
|
||||
|
||||
if (child == NULL && thisChild != NULL) {
|
||||
// the name was not found in the variables or parameters,
|
||||
// but we have a class pointer. Try to find the name in the
|
||||
// list of members.
|
||||
_RequestValueIfNeeded(token, thisChild);
|
||||
ValueNode* thisNode = thisChild->Node();
|
||||
// skip the intermediate pointer
|
||||
if (thisNode->GetType()->Kind() == TYPE_ADDRESS
|
||||
&& thisNode->CountChildren() == 1) {
|
||||
thisChild = thisNode->ChildAt(0);
|
||||
|
||||
_RequestValueIfNeeded(token, thisChild);
|
||||
thisNode = thisChild->Node();
|
||||
if (parentNode == NULL) {
|
||||
ValueNodeChild* thisChild = NULL;
|
||||
for (int32 i = 0; i < container->CountChildren(); i++) {
|
||||
ValueNodeChild* current = container->ChildAt(i);
|
||||
const BString& nodeName = current->Name();
|
||||
if (nodeName == identifierName) {
|
||||
child = current;
|
||||
break;
|
||||
} else if (nodeName == "this")
|
||||
thisChild = current;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < thisNode->CountChildren(); i++) {
|
||||
ValueNodeChild* current = thisNode->ChildAt(i);
|
||||
if (child == NULL && thisChild != NULL) {
|
||||
// the name was not found in the variables or parameters,
|
||||
// but we have a class pointer. Try to find the name in the
|
||||
// list of members.
|
||||
_RequestValueIfNeeded(token, thisChild);
|
||||
ValueNode* thisNode = thisChild->Node();
|
||||
fTokenizer->RewindToken();
|
||||
return _ParseIdentifier(thisNode);
|
||||
}
|
||||
} else {
|
||||
// skip intermediate address nodes
|
||||
if (parentNode->GetType()->Kind() == TYPE_ADDRESS
|
||||
&& parentNode->CountChildren() == 1) {
|
||||
child = parentNode->ChildAt(0);
|
||||
|
||||
_RequestValueIfNeeded(token, child);
|
||||
parentNode = child->Node();
|
||||
fTokenizer->RewindToken();
|
||||
return _ParseIdentifier(parentNode);
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < parentNode->CountChildren(); i++) {
|
||||
ValueNodeChild* current = parentNode->ChildAt(i);
|
||||
const BString& nodeName = current->Name();
|
||||
if (nodeName == identifierName) {
|
||||
child = current;
|
||||
@ -824,8 +857,21 @@ CLanguageExpressionEvaluator::_ParseIdentifier()
|
||||
}
|
||||
|
||||
_RequestValueIfNeeded(token, child);
|
||||
|
||||
ValueNode* node = child->Node();
|
||||
|
||||
token = fTokenizer->NextToken();
|
||||
if (token.type == TOKEN_MEMBER_PTR) {
|
||||
token = fTokenizer->NextToken();
|
||||
if (token.type == TOKEN_IDENTIFIER) {
|
||||
fTokenizer->RewindToken();
|
||||
return _ParseIdentifier(node);
|
||||
} else {
|
||||
throw ParseException("Expected identifier after member "
|
||||
"dereference.", token.position);
|
||||
}
|
||||
} else
|
||||
fTokenizer->RewindToken();
|
||||
|
||||
BVariant variant;
|
||||
Value* nodeValue = node->GetValue();
|
||||
nodeValue->ToVariant(variant);
|
||||
|
@ -72,7 +72,7 @@ class CLanguageExpressionEvaluator {
|
||||
Number _ParseProduct();
|
||||
Number _ParsePower();
|
||||
Number _ParseUnary();
|
||||
Number _ParseIdentifier();
|
||||
Number _ParseIdentifier(ValueNode* parentNode = NULL);
|
||||
Number _ParseAtom();
|
||||
|
||||
void _EatToken(int32 type);
|
||||
|
Loading…
Reference in New Issue
Block a user