10

I am attempting to parse javascript (using javascript), and I've run into a problem with objects. How does javascript determine the difference between an object or a block?

For instance

{ x : 1, y : 2}

Token Stream:

[{][x][:][1][,][y][:][2][}]

Is clearly an object, however

{ var x = 1; var y = 2}

Token Stream:

[{][var][x][=][1][;][var][y][=][2][}]

Is a perfectly valid anonymous javascript block. How would I go about efficiently identifying each token stream as an object or block?

However, more important then both of these how would I determine the difference between a token stream that could be an object or a block like the following:

{ a : null }

Token Stream:

[{][a][:][null][}]

This could either be an object whose parameter a is equal to null, or it could be a block where the first statement in the block (null) has a label (a)

11
  • 2
    It doesn't, actually (at least in Chrome). Try running {x: 1, y: 2} in the console. It won't work; you get a syntax error. You must surround it with parentheses (therefore having it expect an expression rather than a block) and then it works as expected. Commented Nov 11, 2011 at 4:38
  • Ah, yes, so, in order to parse this properly, I must know what comes before it to determine if it will be followed by an object or a block? Commented Nov 11, 2011 at 4:45
  • I just tried the same test with the Node.JS REPL and it recognizes the object literal without parentheses just fine. In the case that it is ambiguous, it seems it chooses the object literal notation. Commented Nov 11, 2011 at 4:45
  • 1
    Actually, while { x : 1, y : 2 } does not work, { x : 1 } is valid Commented Nov 11, 2011 at 4:47
  • 1
    The reason {x:1} is valid is because x here is being used as a label. (Label: developer.mozilla.org/en/JavaScript/Reference/Statements/label) Commented Nov 11, 2011 at 5:36

2 Answers 2

3

You don't.

The context of the syntax affects it's identity. You can't just pluck things out of context and determine what they are.

In the grammar, an object literal is:

'{' (propertyNameAndValueList)? '}'

whereas a block is:

'{' (statementList)? '}'

But literals only exist where expressions are allowed, while blocks exist where statements are allowed. And those aren't the same thing.

So, it's the surrounding context that distinguishes the two forms.

Sign up to request clarification or add additional context in comments.

4 Comments

Actually, you can run a standalone javascript file with just the following: { x : 1 }, and it is perfectly valid. So which would it be? an object literal or a block with a label?
@Greg: It appears from quick testing that in most JavaScript engines it will be interpreted as a block with a label. The only exception I've found as of writing this comment is the Node.JS REPL. (I don't know if it occurs in non-REPL code, and I don't know how I'd find out.)
@Greg - it would be a block. "Literals only exist where expressions are allowed", and so on its own it is not taken as a literal.
@Greg - and that's the point. Taken in isolation, you can not determine what the structure is, it's ambiguous without knowing the context. The same things mean different things in different places.
2

Normally, expressions can be statements, but the production for that in the grammar makes two exceptions:

ExpressionStatement :
    [lookahead ∉ {{, function}] Expression ;

The fonts aren't quite right here, but what they mean is that an Expression can be a statement only if the first token is neither '{' nor 'function'.

It's clarified in this note in Section 12.4 of the ECMAScript 5.1 spec:

NOTE An ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block. Also, an ExpressionStatement cannot start with the function keyword because that might make it ambiguous with a FunctionDeclaration.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.