Почему 019 не является синтаксической ошибкой JavaScript? Или почему 019> 020

Если я наберу 019 > 020 в консоли JavaScript (протестирован как в Chrome, так и в Firefox), я получаю ответ true.

Это связано с тем, что 020 интерпретируется как OctalIntegerLiteral (равно 16), тогда как 019, по-видимому, интерпретируется как DecimalLiteral (и равно 19). Поскольку 19 больше, чем 16, 019 > 020 - true.

Что меня озадачивает, почему 019 интерпретируется как DecimalLiteral на первом месте. Какая она? DecimalIntegerLiteral не позволяет 019:

DecimalIntegerLiteral ::
    0
    NonZeroDigit DecimalDigits_opt

OctalIntegerLiteral также не позволяет 019 (поскольку 9 не является восьмеричной цифрой):

OctalIntegerLiteral ::
    0 OctalDigit
    OctalIntegerLiteral OctalDigit

OctalDigit :: one of
    0 1 2 3 4 5 6 7

Итак, из того, что я вижу в спецификации, 019 должен быть фактически отклонен, я не понимаю, почему он интерпретируется как десятичное целое.

Я предполагаю, что здесь есть какое-то правило совместимости, но я не нашел формального определения. Может ли кто-нибудь помочь мне с этим?

(Почему мне это нужно: я разрабатываю парсер JavaScript/ECMAScript для Java с JavaCC и должен уделять особое внимание спецификация - и их отклонения.)

Ответ 1

Из того, что я мог найти, кажется, что некоторые реализации JavaScript просто не соответствуют спецификации в этой точке.

Из сайта MDN:

Обратите внимание, что десятичные литералы могут начинаться с нуля (0), за которым следует другая десятичная цифра, но если следующая цифра после ведущего 0 равна меньше 8, число анализируется как восьмеричное число. Это не будет в JavaScript, см. ошибка 957513. См. Также страницу о ParseInt().

Это все еще не объясняет, почему 019 == 19, учитывая, что следующая цифра после ведущего 0 равна 1, и поэтому целое число должно анализироваться как восьмеричное. Но связанная ошибка, похоже, связана с вашим делом. В его описании говорится:

Следующая программа JavaScript должна вызывать ошибку:

08

Согласно спецификации, DecimalIntegerLiteral никогда не может быть 0 напрямую за которым следует другая десятичная цифра, хотя Chrome/Opera, PrestOpera, и Firefox поддерживают его.

Ошибка закрыта как WONTFIX

Однако 019 будет действительным десятичным литералом со значением, равным 19, согласно проекту следующего выпуска:

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-syntax-numeric-literals

(Я отметил соответствующие правила)

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

Итак, 01 есть LegacyOctalLikeDecimalIntegerLiteral (3). Тогда 019 есть NonOctalDecimalIntegerLiteral (2), которое, в свою очередь, есть a DecimalIntegerLiteral (1).