Bug 675694: add function to dump parse trees and use it in shell parse function, r=jorendorff

This commit is contained in:
Eddy Bruel 2012-02-08 17:21:33 -08:00
parent 6e66fa3071
commit d4067beac6
4 changed files with 177 additions and 1 deletions

View File

@ -64,6 +64,131 @@ ParseNode::isConstant()
}
}
#ifdef DEBUG
inline void
IndentNewLine(int indent)
{
fputc('\n', stderr);
for (int i = 0; i < indent; ++i)
fputc(' ', stderr);
}
inline void
ParseNode::dump(int indent)
{
switch (pn_arity) {
case PN_NULLARY:
((NullaryNode *) this)->dump();
break;
case PN_UNARY:
((UnaryNode *) this)->dump(indent);
break;
case PN_BINARY:
((BinaryNode *) this)->dump(indent);
break;
case PN_TERNARY:
((TernaryNode *) this)->dump(indent);
break;
case PN_FUNC:
((FunctionNode *) this)->dump(indent);
break;
case PN_LIST:
((ListNode *) this)->dump(indent);
break;
case PN_NAME:
((NameNode *) this)->dump(indent);
break;
default:
fprintf(stderr, "?");
break;
}
}
inline void
NullaryNode::dump()
{
fprintf(stderr, "(%s)", js_CodeName[getOp()]);
}
inline void
UnaryNode::dump(int indent)
{
const char *name = js_CodeName[getOp()];
fprintf(stderr, "(%s ", name);
indent += strlen(name) + 2;
DumpParseTree(pn_kid, indent);
fprintf(stderr, ")");
}
inline void
BinaryNode::dump(int indent)
{
const char *name = js_CodeName[getOp()];
fprintf(stderr, "(%s ", name);
indent += strlen(name) + 2;
DumpParseTree(pn_left, indent);
IndentNewLine(indent);
DumpParseTree(pn_right, indent);
fprintf(stderr, ")");
}
inline void
TernaryNode::dump(int indent)
{
const char *name = js_CodeName[getOp()];
fprintf(stderr, "(%s ", name);
indent += strlen(name) + 2;
DumpParseTree(pn_kid1, indent);
IndentNewLine(indent);
DumpParseTree(pn_kid2, indent);
IndentNewLine(indent);
DumpParseTree(pn_kid3, indent);
fprintf(stderr, ")");
}
inline void
FunctionNode::dump(int indent)
{
const char *name = js_CodeName[getOp()];
fprintf(stderr, "(%s ", name);
indent += strlen(name) + 2;
DumpParseTree(pn_body, indent);
fprintf(stderr, ")");
}
inline void
ListNode::dump(int indent)
{
const char *name = js_CodeName[getOp()];
fprintf(stderr, "(%s ", name);
if (pn_head != NULL) {
indent += strlen(name) + 2;
DumpParseTree(pn_head, indent);
ParseNode *pn = pn_head->pn_next;
while (pn != NULL) {
IndentNewLine(indent);
DumpParseTree(pn, indent);
pn = pn->pn_next;
}
}
fprintf(stderr, ")");
}
inline void
NameNode::dump(int indent)
{
const char *name = js_CodeName[getOp()];
if (isUsed())
fprintf(stderr, "(%s)", name);
else {
fprintf(stderr, "(%s ", name);
indent += strlen(name) + 2;
DumpParseTree(expr(), indent);
fprintf(stderr, ")");
}
}
#endif
inline void
NameNode::initCommon(TreeContext *tc)
{

View File

@ -660,3 +660,14 @@ js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
}
return pn;
}
#ifdef DEBUG
void
js::DumpParseTree(ParseNode *pn, int indent)
{
if (pn == NULL)
fprintf(stderr, "()");
else
pn->dump(indent);
}
#endif

View File

@ -929,12 +929,20 @@ struct ParseNode {
#endif
inline ConditionalExpression &asConditionalExpression();
inline PropertyAccess &asPropertyAccess();
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct NullaryNode : public ParseNode {
static inline NullaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (NullaryNode *)ParseNode::create(kind, PN_NULLARY, tc);
}
#ifdef DEBUG
inline void dump();
#endif
};
struct UnaryNode : public ParseNode {
@ -947,6 +955,10 @@ struct UnaryNode : public ParseNode {
static inline UnaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (UnaryNode *)ParseNode::create(kind, PN_UNARY, tc);
}
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct BinaryNode : public ParseNode {
@ -967,6 +979,10 @@ struct BinaryNode : public ParseNode {
static inline BinaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (BinaryNode *)ParseNode::create(kind, PN_BINARY, tc);
}
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct TernaryNode : public ParseNode {
@ -983,24 +999,40 @@ struct TernaryNode : public ParseNode {
static inline TernaryNode *create(ParseNodeKind kind, TreeContext *tc) {
return (TernaryNode *)ParseNode::create(kind, PN_TERNARY, tc);
}
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct ListNode : public ParseNode {
static inline ListNode *create(ParseNodeKind kind, TreeContext *tc) {
return (ListNode *)ParseNode::create(kind, PN_LIST, tc);
}
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct FunctionNode : public ParseNode {
static inline FunctionNode *create(ParseNodeKind kind, TreeContext *tc) {
return (FunctionNode *)ParseNode::create(kind, PN_FUNC, tc);
}
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct NameNode : public ParseNode {
static NameNode *create(ParseNodeKind kind, JSAtom *atom, TreeContext *tc);
inline void initCommon(TreeContext *tc);
#ifdef DEBUG
inline void dump(int indent);
#endif
};
struct NameSetNode : public ParseNode {
@ -1254,6 +1286,10 @@ class PropertyByValue : public ParseNode {
ParseNode *
CloneLeftHandSide(ParseNode *opn, TreeContext *tc);
#ifdef DEBUG
void DumpParseTree(ParseNode *pn, int indent = 0);
#endif
/*
* js::Definition is a degenerate subtype of the PN_FUNC and PN_NAME variants
* of js::ParseNode, allocated only for function, var, const, and let

View File

@ -3704,8 +3704,12 @@ Parse(JSContext *cx, uintN argc, jsval *vp)
js::Parser parser(cx);
parser.init(JS_GetStringCharsZ(cx, scriptContents), JS_GetStringLength(scriptContents),
"<string>", 0, cx->findVersion());
if (!parser.parse(NULL))
ParseNode *pn = parser.parse(NULL);
if (!pn)
return JS_FALSE;
#ifdef DEBUG
DumpParseTree(pn);
#endif
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}