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)
2 Answers 2
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.
4 Comments
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.
{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.{x:1}is valid is becausexhere is being used as a label. (Label: developer.mozilla.org/en/JavaScript/Reference/Statements/label)