Why is 019 not a JavaScript syntax error? Or why is 019 > 020
JavascriptGrammarLanguage LawyerEcmascript 5JavaccJavascript Problem Overview
If I type 019 > 020
in the JavaScript console (tested in both Chrome and Firefox), I get the answer true
.
This is due to 020
being interpreted as an OctalIntegerLiteral
(equals 16
) whereas 019
is apparently being interpreted as DecimalLiteral
(and equals 19
). As 19
is greater than 16
, 019 > 020
is true
.
What puzzles me is why 019
is interpreted as a DecimalLiteral
in first place. Which production is it? DecimalIntegerLiteral
does not allow 019
:
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits_opt
OctalIntegerLiteral
also does not allow 019
(as 9
is not an octal digit):
OctalIntegerLiteral ::
0 OctalDigit
OctalIntegerLiteral OctalDigit
OctalDigit :: one of
0 1 2 3 4 5 6 7
So from what I see in the specification, 019
should actually be rejected, I don't see why it is interpreted as a decimal integer.
I guess there's some kind of compatibility rule in place here but I have failed to find a formal definition. Could please anyone help me with this?
(Why I need this: I'm developing a JavaScript/ECMAScript parser for Java with JavaCC and have to pay a special attention to the specification - and deviations thereof.)
Javascript Solutions
Solution 1 - Javascript
From what I could find, it seems that some implementations of JavaScript just don't follow the spec on that point.
From the MDN site:
> Note that decimal literals can start with a zero (0) followed by > another decimal digit, but If the next digit after the leading 0 is > smaller than 8, the number gets parsed as an octal number. This won't > throw in JavaScript, see bug 957513. See also the page about > parseInt().
This still doesn't explain why 019 == 19
, given that the next digit after the leading 0 is 1 and the whole number should therefore be parsed as octal. But the referenced bug does seem related to your case. Its description says:
> The following JavaScript program should throw an error:
>
> 08
>
> As per the spec, DecimalIntegerLiteral
can never be 0
directly
> followed by another decimal digit, although Chrome/Opera, PrestOpera,
> and Firefox do support it.
The bug is closed as WONTFIX
However, 019
would be a valid decimal literal, with value equal to 19, according to the draft of the next edition:
https://people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-syntax-numeric-literals
(I've marked the relevant rules)
The syntax and semantics of 11.8.3 is extended as follows except that
this extension is not allowed for strict mode code:
[...]
DecimalIntegerLiteral ::
0
NonZeroDigit DecimalDigits_opt
NonOctalDecimalIntegerLiteral // (1)
NonOctalDecimalIntegerLiteral ::
0 NonOctalDigit
LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit // (2)
NonOctalDecimalIntegerLiteral DecimalDigit
LegacyOctalLikeDecimalIntegerLiteral ::
0 OctalDigit // (3)
LegacyOctalLikeDecimalIntegerLiteral OctalDigit
So 01
is a LegacyOctalLikeDecimalIntegerLiteral
(3) . Then 019
is a NonOctalDecimalIntegerLiteral
(2) which in turn is a DecimalIntegerLiteral
(1).