public override void Visit(TypeOfNode node) { if (node != null) { // depth-first base.Visit(node); if (m_parser.Settings.IsModificationAllowed(TreeModifications.EvaluateNumericExpressions)) { // see if our operand is a ConstantWrapper ConstantWrapper literalOperand = node.Operand as ConstantWrapper; if (literalOperand != null) { // either number, string, boolean, or null. // the operand is a literal. Therefore we already know what the typeof // operator will return. Just short-circuit that behavior now and replace the operator // with a string literal of the proper value string typeName = null; if (literalOperand.IsStringLiteral) { // "string" typeName = "string"; } else if (literalOperand.IsNumericLiteral) { // "number" typeName = "number"; } else if (literalOperand.IsBooleanLiteral) { // "boolean" typeName = "boolean"; } else if (literalOperand.Value == null) { // "object" typeName = "object"; } if (!string.IsNullOrEmpty(typeName)) { node.Parent.ReplaceChild(node, new ConstantWrapper(typeName, PrimitiveType.String, node.Context, m_parser)); } } else if (node.Operand is ObjectLiteral) { node.Parent.ReplaceChild(node, new ConstantWrapper("object", PrimitiveType.String, node.Context, m_parser)); } } } }
//--------------------------------------------------------------------------------------- // ParseUnaryExpression // // UnaryExpression : // PostfixExpression | // 'delete' UnaryExpression | // 'void' UnaryExpression | // 'typeof' UnaryExpression | // '++' UnaryExpression | // '--' UnaryExpression | // '+' UnaryExpression | // '-' UnaryExpression | // '~' UnaryExpression | // '!' UnaryExpression // //--------------------------------------------------------------------------------------- private AstNode ParseUnaryExpression(out bool isLeftHandSideExpr, bool isMinus) { AstNode ast = null; isLeftHandSideExpr = false; bool dummy = false; Context exprCtx = null; AstNode expr = null; switch (m_currentToken.Token) { case JSToken.Void: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new VoidNode(exprCtx, this, expr); break; case JSToken.TypeOf: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new TypeOfNode(exprCtx, this, expr); break; case JSToken.Plus: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new NumericUnary(exprCtx, this, expr, JSToken.Plus); break; case JSToken.Minus: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, true); exprCtx.UpdateWith(expr.Context); ast = new NumericUnary(exprCtx, this, expr, JSToken.Minus); break; case JSToken.BitwiseNot: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new NumericUnary(exprCtx, this, expr, JSToken.BitwiseNot); break; case JSToken.LogicalNot: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new NumericUnary(exprCtx, this, expr, JSToken.LogicalNot); break; case JSToken.Delete: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new Delete(exprCtx, this, expr); break; case JSToken.Increment: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new PostOrPrefixOperator(exprCtx, this, expr, m_currentToken.Token, PostOrPrefix.PrefixIncrement); break; case JSToken.Decrement: exprCtx = m_currentToken.Clone(); GetNextToken(); expr = ParseUnaryExpression(out dummy, false); exprCtx.UpdateWith(expr.Context); ast = new PostOrPrefixOperator(exprCtx, this, expr, m_currentToken.Token, PostOrPrefix.PrefixDecrement); break; default: m_noSkipTokenSet.Add(NoSkipTokenSet.s_PostfixExpressionNoSkipTokenSet); try { ast = ParseLeftHandSideExpression(isMinus); } catch (RecoveryTokenException exc) { if (IndexOfToken(NoSkipTokenSet.s_PostfixExpressionNoSkipTokenSet, exc) == -1) { throw; } else { if (exc._partiallyComputedNode == null) SkipTokensAndThrow(); else ast = exc._partiallyComputedNode; } } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_PostfixExpressionNoSkipTokenSet); } ast = ParsePostfixExpression(ast, out isLeftHandSideExpr); break; } return ast; }
public override void Visit(TypeOfNode node) { // same logic for most nodes TypicalHandler(node); }