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:
Rene Gollent 2014-10-30 09:51:45 -04:00
parent 824404e31f
commit 5cd3ae7c0d
2 changed files with 80 additions and 34 deletions

View File

@ -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);

View File

@ -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);