Исходный текст программы на ECMAScript предварительно преобразуется в последовательность входных элементов, которые представляют собой токены, символы окончания строки, комментарии или пробельные символы. Исходный текст анализируется слева направо, каждый раз принимая максимально возможную последовательность символов за следующий входной элемент.
В этой лексической грамматике существует два начальных символа. Символ InputElementDiv Входной элемент деления используется в контекстах синтаксической грамматики, в которых допускается использование оператора деления (/
) или деления-с-присвоением (/=
). В других контекстах синтаксической грамматики используется символ InputElementRegExp Входной элемент регулярного выражения.
ПРИМЕЧАНИЕ Нет таких контекстов синтаксической грамматики, где были бы допустимы одновременно и деление либо деление-с-присвоением, и ведущий RegularExpressionLiteral Литерал регулярного выражения. Подстановка точки с запятой (см. 7.9) на это не влияет. В таких примерах, как:
a = b
/hi/g.exec(c).map(d);
(где после LineTerminator первым символом, отличным от пробельного и не относящимся к комментарию, является символ "косая черта" (/
), и где в соответствии с синтаксическим контекстом допускается деление или деление-с-присвоением), возле символа LineTerminator нет точки с запятой. То есть, толкование вышеприведенного примера должно быть следующим:
a = b / hi / g.
exec
(c).map(d);
Синтаксис
InputElementDiv ::
WhiteSpace
LineTerminator
Comment
Token
DivPunctuator
InputElementRegExp ::
WhiteSpace
LineTerminator
Comment
Token
RegularExpressionLiteral
Символы управления форматом в стандарте Юникод – то есть, символы в категории "Cf" в базе данных символов Юникода, такие как left-to-right mark метка слева направо или right-to-left mark метка справа налево – являются управляющими кодами для управления форматированием определенного фрагмента текста при отсутствии используемых для этой цели протоколов более высокого уровня (таких как языки разметки).
Для облегчения редактирования и вывода на экран полезно разрешить включение в исходный текст символов управления форматом. Все эти символы могут использоваться как часть комментариев, а также как часть строковых литералов и литералов регулярных выражений.
Символы управления форматом <ZWNJ> и <ZWJ> используются для того, чтобы обеспечить необходимые различия при образовании слов или фраз в определенных языках. В исходном тексте на ECMAScript эти символы <ZWNJ> и <ZWJ> также могут применяться как идентификатор после первого символа.
Символ форматирования <BOM> используется преимущественно в начале текста. Он помечает его как текст в Юникоде и позволяет определить кодировку текста и порядок байтов. Символы <BOM>, предназначенные для этой цели, также могут иногда появляться не в начале текста, а далее – это может быть, например, результатом объединения нескольких файлов в один. Символы <BOM> интерпретируются как пробельные символы (см. 7.2).
В Таблице 1 приводится трактовка определенных символов форматирования, которые не являются частью комментариев, строковых литералов и регулярных выражений.
Значение кодовой единицы |
Наименование |
Официальное название |
Употребление |
|
Нулевая ширина без объединения |
<ZWNJ> |
IdentifierPart |
|
Объединитель нулевой ширины |
<ZWJ> |
IdentifierPart |
|
Метка порядка байтов |
<BOM> |
Whitespace |
Пробельные символы применяются в целях удобочитаемости исходного текста и для разделения токенов (неделимых лексических единиц). Никакого другого значения они не имеют. Встретиться они могут между двумя токенами, а также в начале или в конце ввода. Кроме того, пробельные символы могут встретиться внутри StringLiteral Строковый литерал или RegularExpressionLiteral Литерал регулярного выражения, где они считаются значимыми символами, образующими часть значения этого литерала, или в рамках Comment Комментарий. Больше ни в каком другом токене они не могут встретиться.
В Таблице 2 перечислены пробельные символы ECMAScript.
Значение кодовой единицы |
Наименование |
Официальное название |
|
Табуляция |
<TAB> |
|
Вертикальная табуляция |
<VT> |
|
Перевод страницы |
<FF> |
|
Пробел |
<SP> |
|
Неразрывный пробел |
<#x0a> |
Другая категория “Zs” |
Метка порядка байтов Любой другой "пробельный разделитель" Юникода |
<BOM> <USP> |
Реализации ECMAScript должны распознавать все пробельные символы, определенные в формате Юникод версии 3.0. Более поздние версии стандарта Юникод могут определять другие пробельные символы. Реализации ECMAScript могут распознавать пробельные символы из более поздних версий Юникода.
Синтаксис
WhiteSpace ::
<TAB>
<VT>
<FF>
<SP>
<#x0a>
<BOM>
<USP>
Как и пробельные символы, символы окончания строки применяются в целях удобочитаемости исходного текста и для разделения токенов (неделимых лексических единиц). Однако, в отличие от пробельных символов, символы окончания строки некоторым образом влияют на поведение синтаксической грамматики.
Символы окончания строки могут встретиться между любыми двумя токенами, однако в некоторых местах синтаксическая грамматика запрещает их применение. Кроме того, эти символы затрагивают процесс автоматической подстановки точки с запятой (7.9). Символ окончания строки не может использоваться внутри какого-либо токена, кроме StringLiteral, причем в этом случае он может использоваться в StringLiteral как часть LineContinuation Продолжение строки.
Символ окончания строки может встретиться внутри MultiLineComment Многострочный комментарий – см. 7.4, но не может встретиться в SingleLineComment Однострочный комментарий.
Символы окончания строки включены в набор пробельных символов, которым соответствует класс \s
в регулярных выражениях.
В Таблице 3 перечислены символы окончания строки ECMAScript.
Значение кодовой единицы |
Наименование |
Официальное название |
|
Перевод строки |
<LF> |
|
Возврат каретки |
<CR> |
|
Разделитель строки |
<LS> |
|
Разделитель параграфа |
<PS> |
Символами окончания строки являются только те символы, которые приведены в Таблице 3. Все другие символы новой строки или переноса строки интерпретируются не как символы окончания строки, а как пробельные символы. В качестве окончания строки часто используется последовательность символов <CR><LF>. При нумерации строк ее следует рассматривать как один символ.
Синтаксис
LineTerminator ::
<LF>
<CR>
<LS>
<PS>
LineTerminatorSequence ::
<LF>
<CR> [lookahead ∉ <LF> ]
<LS>
<PS>
<CR> <LF>
Комментарии могут быть однострочными или многострочными, причем последние не могут образовывать вложений.
Поскольку однострочный комментарий может содержать любой символ, кроме символа LineTerminator, а также в соответствии с общим правилом о том, что токен должен быть как можно длиннее, однострочный комментарий всегда включает в себя все символы между маркером //
и концом строки. Однако стоящий в конце строки символ LineTerminator не считается частью однострочного комментария. Он распознается лексической грамматикой отдельно и становится частью потока входных элементов для синтаксической грамматики. Этот момент очень важен, поскольку он свидетельствует о том, что наличие или отсутствие однострочных комментариев не влияет на процесс автоматической подстановки точки с запятой (см. 7.9).
Поведение комментариев аналогично поведению пробельных символов. Как правило, комментарии игнорируются, за исключением того, что если MultiLineComment содержит символ окончания строки, в этом случае весь комментарий, в целях его анализа синтаксической грамматикой, принимается за LineTerminator.
Синтаксис
Comment ::
MultiLineComment
SingleLineComment
MultiLineComment ::
/*
MultiLineCommentCharsopt*/
MultiLineCommentChars ::
MultiLineNotAsteriskChar MultiLineCommentCharsopt*
PostAsteriskCommentCharsopt
PostAsteriskCommentChars ::
MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt*
PostAsteriskCommentCharsopt
MultiLineNotAsteriskChar::
SourceCharacter но не asterisk *
MultiLineNotForwardSlashOrAsteriskChar ::
SourceCharacter но не forward-slash /
или asterisk *
SingleLineComment ::
//
SingleLineCommentCharsopt
SingleLineCommentChars ::
SingleLineCommentChar SingleLineCommentCharsopt
SingleLineCommentChar ::
SourceCharacter но не LineTerminator
Синтаксис
Token ::
IdentifierName
Punctuator
NumericLiteral
StringLiteral
ПРИМЕЧАНИЕ Правила для DivPunctuator и RegularExpressionLiteral определяют токены, но не включены в правило для Token.
Имена идентификаторов представляют собой токены, толкование которых производится в соответствии с грамматикой, описанной в разделе "Идентификаторы" Главы 5 стандарта Юникод (с небольшими изменениями). Identifier Идентификатор представляет собой IdentifierName Имя идентификатора, которое не является ReservedWord Зарезервированное слово – см. 7.6.1. В основе грамматики идентификаторов Юникода лежат нормативные и информативные категории символов, описываемые стандартом Юникод. Все реализации ECMAScript, соответствующие требованиям данного Стандарта, должны обрабатывать символы в упомянутых категориях стандарта Юникод версии 3.0 как принадлежащие к этим категориям.
Этот стандарт добавляет еще два специфических символа: Знак доллара ($
) и символ подчёркивания (_
) — они допускаются в любом месте IdentifierName.
Кроме того, в IdentifierName допускаются и управляющие последовательности Юникода Unicode escape sequences: они трактуются как один символ IdentifierName, вычисленный символьным значением UnicodeEscapeSequence Юникодная управляющая последовательность – см. 7.8.4). Обратная косая черта \
, стоящая перед UnicodeEscapeSequence, не трактуется как символ IdentifierName. UnicodeEscapeSequence не может использоваться для того, чтобы вставить в IdentifierName символ, который в противном случае был бы некорректным. Иными словами, если последовательность \
UnicodeEscapeSequence заменить на символьное значение для UnicodeEscapeSequence, результатом все равно должен являться корректный IdentifierName с точно такой же последовательностью символов, что и в оригинальном IdentifierName. В основе интерпретации всех идентификаторов в данной спецификации лежат их фактические символы, независимо от того, использовалась ли управляющая последовательность для передачи каких-либо конкретных символов.
Два символа IdentifierName, канонически эквивалентные в соответствии со стандартом Юникода, не являются одинаковыми, если они не представлены совершенно одинаковыми последовательностями кодовых единиц (иными словами, корректные реализации ECMAScript должны производить только побитовое сравнение значений IdentifierName). Смысл в том, чтобы прежде чем достичь компилятора, входящий исходный текст преобразовывался бы в соответствии с формой нормализации "С".
Реализации ECMAScript могут распознавать символы идентификатора из более поздних версий Юникода. В случае возможных проблем с межплатформенной переносимостью программы, при написании кода следует использовать только символы, описанные в стандарте Юникод версии 3.0.
Синтаксис
Identifier ::
IdentifierName но не ReservedWord
IdentifierName ::
IdentifierStart
IdentifierName IdentifierPart
IdentifierStart ::
UnicodeLetter$
_\
UnicodeEscapeSequence
IdentifierPart ::
IdentifierStart
UnicodeCombiningMark
UnicodeDigit
UnicodeConnectorPunctuation
<ZWNJ>
<ZWJ>
UnicodeLetter
– любой символ в категориях Юникода “Прописная буква (Lu)”, “Строчная буква (Ll)”, “Заглавная буква (Lt)”, “Буква-модификатор (Lm)”, “Другая буква (Lo)” или “Буква-число (Nl)”.
UnicodeCombiningMark
– любой символ в категориях Юникода “Не-пробельный знак (Mn)” или “Комбинирующий пробельный знак (Mc)”
UnicodeDigit
– любой символ в категории Юникода “Десятичное число (Nd)”
UnicodeConnectorPunctuation
– любой символ в категории Юникода “Соединяющая пунктуация (Pc)”
UnicodeEscapeSequence
– см. пункт 7.8.4.
IdentifierName, которое не может быть использовано как Identifier, является зарезервированным словом.
Синтаксис
ReservedWord ::
Keyword
FutureReservedWord
NullLiteral
BooleanLiteral
Перечисленные ниже токены являются ключевыми словами ECMAScript. В программах на ECMAScript они не могут быть использованы как Identifiers Идентификаторы.
Синтаксис
Keyword :: одно из
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Перечисленные ниже слова используются как ключевые слова в предполагаемых расширениях языка. Они зарезервированы, чтобы предусмотреть возможность применения этих расширений в будущем.
Синтаксис
FutureReservedWord :: одно из
|
|
|
|
|
|
|
Перечисленные ниже токены также рассматриваются как FutureReservedWords Зарезервированные на будущее слова если они встречаются в программе, написанной в строгом режиме языка (см. 10.1.1). Если в каком-либо контексте, в котором использование FutureReservedWord Зарезервированное на будущее слово вызвало бы ошибку, появится какой-либо из перечисленных ниже токенов в строгом режиме, это также должно вызвать аналогичную ошибку.
|
|
|
|
|
|
|
|
|
Синтаксис
Punctuator :: одно из
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DivPunctuator :: одно из
|
|
Синтаксис
Literal ::
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
RegularExpressionLiteral
Синтаксис
NullLiteral ::
null
Семантика
Значением литерала null null
является единственное значение типа Null, а именно – null.
Синтаксис
BooleanLiteral ::
true
false
Семантика
Значением литерала Boolean true
является значение типа Boolean, а именно – true.
Значением литерала Boolean false
является значение типа Boolean, а именно – false.
Синтаксис
NumericLiteral ::
DecimalLiteral
HexIntegerLiteral
DecimalLiteral ::
DecimalIntegerLiteral .
DecimalDigitsopt ExponentPartopt.
DecimalDigits ExponentPartopt
DecimalIntegerLiteral ExponentPartopt
DecimalIntegerLiteral::
0
NonZeroDigit DecimalDigitsopt
DecimalDigits ::
DecimalDigit
DecimalDigits DecimalDigit
DecimalDigit :: одно из
0 1 2 3 4 5 6 7 8 9
НенулеваяЦифра :: одно из
1 2 3 4 5 6 7 8 9
ExponentPart ::
ExponentIndicator SignedInteger
ExponentIndicator :: одно из
e E
SignedInteger ::
DecimalDigits+
DecimalDigits-
DecimalDigits
HexIntegerLiteral ::
0x
HexDigit0X
HexDigit
HexIntegerLiteral HexDigit
HexDigit :: одно из
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
Исходный символ, следующий сразу же за NumericLiteral Числовой литерал, не должен быть IdentifierStart Начало идентификатора или DecimalDigit Десятичная цифра.
ПРИМЕЧАНИЕ Например, запись:
3in
не представляет собой два входные элемента 3
и in
, а является ошибкой.
Семантика
Числовой литерал имеет значение типа Number. Это значение определяется в два этапа: сначала из литерала выводится его математическое значение MV (сокращение от "mathematical value" – прим. перев.), а затем это MV округляется в соответствии с приведенными ниже описаниями:
MV NumericLiteral :: DecimalLiteral равно MV DecimalLiteral.
MV NumericLiteral :: HexIntegerLiteral равно MV HexIntegerLiteral.
MV DecimalLiteral ::DecimalIntegerLiteral .
равно MV DecimalIntegerLiteral.
MV DecimalLiteral ::DecimalIntegerLiteral .
DecimalDigits равно MV DecimalIntegerLiteral плюс (MV DecimalDigits, умноженное на 10–n), гдн n – количество символов в DecimalDigits.
MV DecimalLiteral ::DecimalIntegerLiteral .
ExponentPart равно MV DecimalIntegerLiteral, умноженного на 10e, где e – MV ExponentPart.
MV DecimalLiteral ::DecimalIntegerLiteral .
DecimalDigits ExponentPart равно (MV DecimalIntegerLiteral плюс (MV DecimalDigits , умноженное на 10–n)) умноженное на 10e, где n – количество символов в DecimalDigits, а e
– умноженное ExponentPart.
MV DecimalLiteral ::.
DecimalDigits равно MV DecimalDigits, умноженное на 10–n, где n – кодичество символов в DecimalDigits.
MV DecimalLiteral ::.
DecimalDigits ExponentPart равно MV DecimalDigits, умноженного на 10e–n, где n – количество символов в DecimalDigits, а e – MV ExponentPart.
MV DecimalLiteral ::DecimalIntegerLiteral равно MV DecimalIntegerLiteral.
MV DecimalLiteral ::DecimalIntegerLiteral ExponentPart равно MV DecimalIntegerLiteral, умноженому на 10e, где e – MV ExponentPart.
MV ДесятичногоЦелогоЛитерала :: 0
является 0.
MV DecimalIntegerLiteral :: NonZeroDigit DecimalDigits равно (MV NonZeroDigit , умноженное на 10n) плюс MV DecimalDigits, где n – количество символов в DecimalDigits.
MV DecimalDigits :: DecimalDigit равно MV DecimalDigit.
MV DecimalDigits :: DecimalDigits DecimalDigit равно (MV DecimalDigits, умноженное на 10) плюс MV DecimalDigit.
MV ExponentPart ::ExponentIndicator SignedInteger равно MV SignedInteger.
MV SignedInteger ::DecimalDigits равно DecimalDigits.
MV SignedInteger ::+
DecimalDigits равно DecimalDigits.
MV SignedInteger ::-
DecimalDigits равно отрицательному MV DecimalDigits.
MV для DecimalDigit :: 0
или для HexDigit :: 0
равно 0.
MV для DecimalDigit :: 1
или для NonZeroDigit :: 1
или для HexDigit :: 1
равно 1.
MV для DecimalDigit :: 2
или для NonZeroDigit :: 2
или для HexDigit :: 2
равно 2.
MV для DecimalDigit :: 3
или для NonZeroDigit :: 3
или для HexDigit :: 3
равно 3.
MV для DecimalDigit :: 4
или для NonZeroDigit :: 4
или для HexDigit :: 4
является 4.
MV для DecimalDigit :: 5
или для NonZeroDigit :: 5
или для HexDigit :: 5
равно 5.
MV ДесятичнойЦифры :: 6
или для NonZeroDigit :: 6
или для HexDigit :: 6
равно 6.
MV для DecimalDigit :: 7
или для NonZeroDigit :: 7
или для HexDigit :: 7
равно 7.
MV для DecimalDigit :: 8
или для NonZeroDigit :: 8
или для HexDigit :: 8
равно 8.
MV DecimalDigit :: 9
или для NonZeroDigit :: 9
или для HexDigit :: 9
равно 9.
MV для HexDigit :: a
или для HexDigit :: A
равно 10.
MV для HexDigit :: b
или для HexDigit :: B
равно 11.
MV для HexDigit :: c
или для HexDigit :: C
равно 12.
MV для HexDigit :: d
или для HexDigit :: D
равно 13.
MV для HexDigit :: e
или для HexDigit :: E
равно 14.
MV для HexDigit :: f
или для HexDigit :: F
равно 15.
MV HexIntegerLiteral :: 0x
HexDigit равно MV HexDigit.
MV HexIntegerLiteral :: 0X
HexDigit равно MV HexDigit.
MV HexIntegerLiteral :: HexIntegerLiteral HexDigit равно (MV HexIntegerLiteral, умноженое на 16) плюс MV HexDigit.
После определения точного MV числового литерала оно затем округляется до значения типа Number. Если MV равно 0, тогда округленное значение равно +0; в противном случае округленное значение должно представлять собой именно это числовое значение MV (в соответствии с определением в пункте 8.5), за исключением случаев, когда литерал является DecimalLiteral и имеет более 20 значимых чисел – в этом случае числовое значение может быть либо числовым значением MV литерала, полученного при замене на число 0
каждой значащей цифры после 20-й, либо числовым значением MV литерала, полученного в результате замены на число 0
каждой значащей цифры после 20-й, с последующим приращением литерала в позиции 20-й значащей цифры. Цифра является значащей, если она не является частью ExponentPart, и
она не является 0
; или
слева от нее находится ненулевая цифра, и справа от нее, не в ExponentPart, тоже находится ненулевая цифра.
В корректной реализации при обработки программы в строгом режиме (см. пункт 10.1.1) синтаксис для NumericLiteral не должен распространяться на OctalIntegerLiteral Восьмеричный целый литерал, определение которого содержится в B.1.1.
Строковый литерал представляет собой символы в количестве ноль или более, заключённые в одиночные или двойные кавычки. Каждый символ может быть представлен управляющей последовательностью. В строковом литерале могут появляться буквально все символы, кроме символа закрывающей кавычки, обратной косой черты, возврата каретки, разделителя строки, разделителя параграфа и перевода строки. Каждый символ может быть представлен в виде управляющей последовательности.
Синтаксис
StringLiteral ::
"
DoubleStringCharactersopt"
SingleStringCharactersopt
''
DoubleStringCharacters ::
DoubleStringCharacter DoubleStringCharactersopt
SingleStringCharacters ::
SingleStringCharacter SingleStringCharactersopt
DoubleStringCharacter ::
SourceCharacter но не double-quote "
или backslash \
или LineTerminator\
EscapeSequence
LineContinuation
SingleStringCharacter ::
SourceCharacter но не single-quote '
или backslash \
или LineTerminator\
EscapeSequence
LineContinuation
LineContinuation ::
\
LineTerminatorSequence
EscapeSequence ::
CharacterEscapeSequence0
[lookahead ∉ DecimalDigit]
HexEscapeSequence
UnicodeEscapeSequence
CharacterEscapeSequence ::
SingleEscapeCharacter
NonEscapeCharacter
SingleEscapeCharacter ::одно из
' " \ b f n r t v
NonEscapeCharacter::
SourceCharacter но не EscapeCharacter или LineTerminator
EscapeCharacter ::
SingleEscapeCharacter
DecimalDigitx
u
HexEscapeSequence ::
x
HexDigit HexDigit
UnicodeEscapeSequence ::
u
HexDigit HexDigit HexDigit HexDigit
Определения нетерминального HexDigit Шестнадцатеричная цифра содержится в пункте 7.6. Определение SourceCharacter Исходный символ содержится в пункте 6.
Семантика
Строковый литерал представляет собой значение типа String. Строковое значение SV (сокращение от "string value" – прим. перев.) литерала описывается на основе символьных значений CV (сокращение от "character value" – прим. перев.) различных частей строкового литерала. В рамках этого процесса некоторые символы строкового литерала трактуются как имеющие математическое значение MV в соответствии с описанием, приведенным ниже или в пункте 7.8.3.
SV StringLiteral :: ""
представляет собой пустую последовательность символов.
SV StringLiteral :: ''
представляет собой пустую последовательность символов.
SV StringLiteral :: "
DoubleStringCharacters "
равно SV DoubleStringCharacters.
SV StringLiteral :: '
SingleStringCharacters '
равно SV SingleStringCharacters.
SV DoubleStringCharacters :: DoubleStringCharacter представляет собой последовательность из одного символа – CV DoubleStringCharacter.
SV DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharacters представляет собой последовательность из CV DoubleStringCharacter, за которым следуют все символы SV DoubleStringCharacters по порядку.
SV SingleStringCharacters :: SingleStringCharacter представляет собой последовательность из одного символа – CV SingleStringCharacter.
SV SingleStringCharacters :: SingleStringCharacter SingleStringCharacters представляет собой последовательность из CV SingleStringCharacter, за которым следуют все символы SV SingleStringCharacters по порядку.
SV LineContinuation :: \
LineTerminatorSequence равно пустой последовательности символов.
CV DoubleStringCharacter :: SourceCharacter но не double-quote "
или backslash \
или LineTerminator равно самому SourceCharacter.
CV DoubleStringCharacter :: \
EscapeSequence равно CV EscapeSequence.
CV DoubleStringCharacter :: LineContinuation равно пустой последовательности символов.
CV SingleStringCharacter :: SourceCharacter но не single-quote '
или backslash \
или LineTerminator равно самому SourceCharacter.
CV SingleStringCharacter ::\
EscapeSequence равно CV EscapeSequence.
CV SingleStringCharacter :: LineContinuation равно пустой последовательности символов.
CV EscapeSequence :: CharacterEscapeSequence равно CV CharacterEscapeSequence.
CV EscapeSequence :: 0
[lookahead ∉ DecimalDigit] равно символу <NUL> (код Юникода 0000).
CV EscapeSequence :: HexEscapeSequence равно CV HexEscapeSequence.
CV EscapeSequence :: UnicodeEscapeSequence равно CV UnicodeEscapeSequence.
CV CharacterEscapeSequence :: SingleEscapeCharacter представляет собой символ, чьё значение кодовой единицы определяется theSingleEscapeCharacter в соответствии с Таблицей 4:
Управляющая последовательность |
Значение кодовой единицы |
Наименование |
Символ |
|
|
возврат |
<BS> |
|
|
горизонтальная табуляция |
<HT> |
|
|
перевод строки (новая строка) |
<LF> |
|
|
вертикальная табуляция |
<VT> |
|
|
перевод страницы |
<FF> |
|
|
возврат каретки |
<CR> |
|
|
двойная кавычка |
|
|
|
одинарная кавычка |
|
|
|
обратная косая |
|
CV CharacterEscapeSequence :: NonEscapeCharacter равно CV NonEscapeCharacter.
CV NonEscapeCharacter :: SourceCharacter но не EscapeCharacter или LineTerminator равно самому SourceCharacter.
CV HexEscapeSequence :: x
HexDigit HexDigit представляет собой символ, чьё значение кодовой единицы равно (16 умноженное на MV первого HexDigit) плюс МЗ второго HexDigit.
CV UnicodeEscapeSequence :: u
HexDigit HexDigit HexDigit HexDigit представляет собой символ, чьё значение кодовой единицы равно (4096 умноженное на MV первого HexDigit) плюс (256 умноженное на MV второго HexDigit) плюс (16 умноженное на MV третьего HexDigit) плюс MV четвертого HexDigit.
В корректной реализации при обработке программы в строгом режиме (см. пункт 10.1.1) синтаксис для EscapeSequence не может распространяться на OctalEscapeSequence, определение которой содержится в B.1.2.
ПРИМЕЧАНИЕ Символ окончания строки не может встретиться в строковом литерале, за исключением случая, когда он как часть LineContinuation используется для создания пустой последовательности символов. Чтобы появление символа окончания строки в строковом значении строкового литерала было корректным, необходимо использовать управляющую последовательность \n
или \u000A
.
Литерал регулярного выражения представляет собой входной элемент, который каждый раз при обработке литерала преобразовывается к объекту RegExp (см. 15.10). Два литерала регулярного выражения в программе преобразовываются к объектам регулярного выражения, которые никогда не сравниваются друг с другом в виде ===
, даже если содержание этих двух литералов идентично. Объект RegExp также может быть создан во время выполнения программы – либо посредством команды new RegExp
(см. 15.10.4), либо с помощью вызова конструктора RegExp
в качестве функции (15.10.3).
Приведённые ниже правила описывают синтаксис литералов регулярного выражения. Эти правила используются предварительным лексическим анализатором (сканером) входного элемента, чтобы найти конец литерала регулярного выражения. Строки символов, составляющих RegularExpressionBody Тело регулярного выражения и RegularExpressionFlags Флаги регулярного выражения, передаются в необработанном виде конструктору регулярных выражений, который затем обрабатывает их в соответствии со своей более строгой грамматикой. Реализация может расширить грамматику конструктора регулярных выражений, однако она не должна расширять правила RegularExpressionBody и RegularExpressionFlags, или правила, используемые этими правилами.
Синтаксис
RegularExpressionLiteral ::
/
RegularExpressionBody /
RegularExpressionFlags
RegularExpressionBody::
RegularExpressionFirstChar RegularExpressionChars
RegularExpressionChars ::
[пусто]
RegularExpressionChars RegularExpressionChar
RegularExpressionFirstChar ::
RegularExpressionNonTerminator но не *
или \
или /
или [
RegularExpressionBackslashSequence
RegularExpressionClass
RegularExpressionChar ::
RegularExpressionNonTerminator но не \
или /
или [
RegularExpressionBackslashSequence
RegularExpressionClass
RegularExpressionBackslashSequence ::
\
RegularExpressionNonTerminator
RegularExpressionNonTerminator ::
SourceCharacter но не LineTerminator
RegularExpressionClass ::
[
RegularExpressionClassChars]
RegularExpressionClassChars::
[пусто]
RegularExpressionClassChars RegularExpressionClassChar
RegularExpressionClassChar::
RegularExpressionNonTerminator но не ]
или \
RegularExpressionBackslashSequence
RegularExpressionFlags::
[пусто]
RegularExpressionFlags IdentifierPart
ПРИМЕЧАНИЕ Литералы регулярного выражения не могут быть пустыми. Символы //
не представляют пустой литерал регулярного выражения – они начинают однострочный комментарий. Чтобы задать пустое регулярное выражение, необходимо использовать /(?:)/
.
Семантика
Литерал регулярного выражения преобразовыается к значению типа Object, который является экземпляром стандартного встроенного конструктора RegExp. Это значение определяется в два этапа: сначала символы, составляющие развёртывания правил RegularExpressionBody и RegularExpressionFlags для регулярных выражений, собираются в необработанном виде в две строки – Pattern Шаблон и Flags Флаги соответственно. Затем каждый раз при оценке литерала создается новый объект посредством выражения new RegExp(
Pattern, Flags
)
, где RegExp является стандартным встроенным конструктором с этим именем. Этот созданный объект становится значением для RegularExpressionLiteral. Если при вызове конструктора new RegExp
получена ошибка, описанная в пункте 15.10.4.1, ее следует обрабатывать как "раннюю ошибку" early error, см. Статью 16.
Некоторые инструкции ECMAScript (пустая инструкция, инструкция переменной, инструкция-выражение, инструкции do
-while
, continue
, break
, return
и throw
) должна завершать точка с запятой. Она всегда может быть указана в исходном тексте явным образом, но иногда её можно опустить, чтобы облегчить чтение кода. В этих случаях говорят, что символы точки с запятой подставляются в поток токенов исходного кода автоматически.
Существует 3 основных правила подстановки точки с запятой:
Если при распознавании программы слева направо встречается "токен-нарушитель" offending token, который ни одно из правил грамматики не разрешает, перед ним происходит автоматическая подстановка точки с запятой, если выполняется одно или оба условия:
Токен-нарушитель отделен от предыдущего токена хотя бы одним LineTerminator.
Токен-нарушитель представляет собой символ }
.
Если при распознавании программы слева направо встречается конец входного потока токенов, и анализатор не может распознать поток входных токенов как единую готовую программу Program на ECMAScript, происходит автоматическая подстановка точки с запятой в конце входного потока.
Если при распознавании программы слева направо встречается токен, разрешенный правилом этой грамматики, однако это правило является ограниченным правилом, и в результате применения этого токен станет первым токеном для терминала или нетерминала, следующего сразу же за комментарием “[no LineTerminator here]”, содержащимся в ограниченном правиле (именно поэтому он и называется "ограниченным токеном"), и ограниченный токен отделен от предыдущего токена хотя бы одним LineTerminator, то перед ограниченным токеном происходит автоматическая подстановка точки с запятой.
Есть еще одно, дополнительное условие, которое перекрывает предыдущие правила. Автоматическая подстановка точки с запятой не производится, если затем эта точка с запятой даст пустую инструкцию, или если она станет одной из двух точек с запятой в заголовке инструкции for
(см. пункт 12.6.3).
ПРИМЕЧАНИЕ Ниже перечислены все ограниченные правила грамматики:
PostfixExpression :
LeftHandSideExpression [no LineTerminator here]
++
LeftHandSideExpression [no LineTerminator here]
--
ContinueStatement :
continue
[no LineTerminator here] Identifier;
BreakStatement :
break
[no LineTerminator here] Identifier;
ReturnStatement :
return
[no LineTerminator here] Expression;
ThrowStatement:
throw
[no LineTerminator here] Expression;
На практике эти ограниченные правила действуют следующим образом:
Если встречается токен ++
или --
там, где анализатор трактует его как постфиксный оператор, и при этом между предыдущим токеном и токеном ++
или --
встречается хотя бы один LineTerminator, тогда перед токеном ++
или --
происходит автоматическая подстановка точки с запятой.
Если встречается токен continue
, break
, return
или throw
, при этом перед следующим токеном встречается LineTerminator, тогда перед токеном continue
, break
, return
или throw
происходит автоматическая подстановка точки с запятой.
Отсюда можно вывести практические советы для программистов, пишущих на ECMAScript:
Постфиксный оператор ++
или --
должен находиться на той же строке, что и его операнд.
Expression Выражение в инструкции return
или throw
должно начинаться на той же строке, что и токен return
или throw
.
Identifier Идентификатор в инструкции break
или continue
должен быть на той же строке, что и токен break
илиcontinue
.
Исходный текст
{ 1 2 } 3
не является корректным предложением в соответствии с правилами грамматики ECMAScript – даже если применить правила автоматической подстановки точки с запятой. В отличие от него, исходный текст
{ 1
2 } 3
также не является корректным предложением ECMAScript, однако посредством автоматической подстановки точки с запятой он преобразовывается в следующее предложение:
{ 1
;2 ;} 3;
которое является корректным предложением ECMAScript.
Исходный текст
for (a; b
)
не является корректным предложением ECMAScript, при этом автоматическая подстановка точки с запятой не изменяет его, так как точка с запятой требуется для заголовка инструкции for
, а, в соответствии с правилами, одна из этих двух точек с запятой не вставляется в заголовок инструкции for
.
Исходный текст
return
a + b
посредством автоматической подстановки точки с запятой преобразовывается в следующее предложение:
return;
a + b;
ПРИМЕЧАНИЕ Выражение a + b
не считается значением, возвращаемым инструкцией return
, так как оно отделено от токена return
LineTerminator.
Исходный текст
a = b
++c
посредством автоматической подстановки точки с запятой преобразовывается в следующее предложение:
a = b;
++c;
ПРИМЕЧАНИЕ Токен ++
не считается постфиксным оператором, применённым к переменной b
, поскольку между b
и ++
находится LineTerminator.
Исходный текст
if (a > b)
else c = d
не является корректным предложением ECMAScript, при этом автоматическая подстановка точки с запятой перед токеном else
не изменяет его, несмотря на то, что в этом месте не применяется никакое правило грамматики, поскольку в этом случае автоматически вставленная точка с запятой была бы воспринята как пустая инструкция.
Исходный текст
a = b + c
(d + e).print()
не преобразовывается в результате автоматической подстановки точки с запятой, поскольку выражение в круглых скобках в начале второй строки может трактоваться как список аргументов для вызова функции:
a = b + c(d + e).print()
Если инструкция присваивания начинается с открывающей скобки, то отличная идея – поставить точку с запятой в конце предыдущей инструкции, а не полагаться на её автоматическую подстановку.