2.1.1.2 Conditional Processing Algorithm

The conditional compilation extension described in this section is not available in EdgeHTML Mode.

For each source text to be processed, let source be the original source text (a sequence of Unicode characters) and let output initially be an empty sequence of Unicode characters. Let IfNestingLevel be 0.

Processing of source proceeds by recognizing specific input elements from source and then taking specified actions. The processing is organized into several states. The specific input elements that are recognized and the subsequent semantic action that is taken varies among states. The semantic action taken for a recognized input element may include transitioning to a different state. Processing of a source text begins by recognizing CCInputElementState0 if SubstitutionEnabled is false and CCInputElementState1 if SubstitutionEnabled is true.

The input elements for conditional processing are defined by the following grammar, which has Unicode characters as terminal symbols. Some rules of the grammar are defined using rules of the ECMAScript lexical grammar.

Syntax

NOTE:

CCInputElementState0 is recognized during top-level conditional processing when SubstitutionEnabled is false. When recognizing a RegularExpressionLiteral in this state, the contextual distinction between RegularExpressionLiteral and DivPunctuator (see [ECMA-262/5] section 7) must be respected.

CCInputElementState0 ::

RegularExpressionLiteralStringLiteralCCOnCCSet0CCIf0CCMultiLineComment0CCSingleLinecomment0SourceCharacter

CCOn ::

@ CCOnId
/*@
CCOnId
//@
CCOnId

CCOnId ::

cc_on [lookahead Ï IdentifierPart ]

CCSet0 ::

@set [lookahead Ï IdentifierPart ]

CCIf0 ::

@if [lookahead Ï IdentifierPart ]

CCMultiLineComment0 ::

/* [lookahead ≠ CCOnId ] MultiLineCommentCharsopt */

SingleLineComment0 ::

// [lookahead ≠ CCOnId ] SingleLineCommentCharsopt

Semantics

If CCInputElementState0 cannot be recognized because there are no remaining characters in source, then Conditional Source processing is completed and the characters of the output supply the Unicode characters for subsequent input element processing. If CCInputElementState0 cannot be recognized and there are characters in source, a SyntaxError exception is thrown.

The productions CCInputElementState0 :: RegularExpressionLiteral, CCInputElementState0 :: StringLiteral, CCInputElementState0 :: CCMultiLineComment0, CCInputElementState0 :: CCSingleLinecomment0, and CCInputElementState0 :: SourceCharacter upon recognition perform the following actions:

  1. Append to the end of output, in left-to-right sequence, the Unicode characters from source that were recognized by the production. Remove the recognized characters from source.

  2. Use CCInputElementState0 to recognize the next input element from source.

The production CCInputElementState0 :: CCOn upon recognition performs the following actions:

  1. Set SubstitutionEnable to true.

  2. Append a <SP> character to the end of output. Remove the recognized characters from source.

  3. Use CCInputElementState1 to recognize the next input element from source.

The production CCInputElementState0 :: CCSet0 upon recognition performs the following actions:

  1. Set SubstitutionEnable to true.

  2. Append a <SP> character to the end of output. Remove the recognized characters from source.

  3. Use CCInputElementStateSetLHS to recognize the next input element from source.

The production CCInputElementState0 :: CCIf0 upon recognition performs the following actions:

  1. Set SubstitutionEnable to true.

  2. Append a <SP> character to the end of output. Remove the recognized characters from source.

  3. Increment the value of IfNestingLevel by 1.

  4. Use CCInputElementStateIfPredicate to recognize the next input element from source.

Syntax

NOTE:

CCInputElementState1 is recognized during active conditional processing when SubstitutionEnabled is true. This may be at the top level or in the clause of an @if statement that represents the "true" condition. When recognizing a RegularExpressionLiteral in this state the contextual distinction between RegularExpressionLiteral and DivPunctuator (see [ECMA-262/5] section 7) must be respected.

CCInputElementState1 ::

RegularExpressionLiteralStringLiteralCCOnCCSet1CCIf1CCElif1CCElse1CCEnd1CCSubstitution1CCStartMarkerCCEndMarkerCCMultiLineComment1CCSingleLinecomment1SourceCharacter

CCSet1 ::

 @set [lookahead Ï IdentifierPart ]
 /*@set [lookahead Ï IdentifierPart ] //@set [lookahead Ï IdentifierPart ]

CCIf1 ::

 @if [lookahead Ï IdentifierPart ]
 /*@if [lookahead Ï IdentifierPart ] //@if [lookahead Ï IdentifierPart ]

CCElif1 ::

 @elif [lookahead Ï IdentifierPart ]
 /*@elif [lookahead Ï IdentifierPart ] //@elif [lookahead Ï IdentifierPart ]

CCElse1 ::

 @else [lookahead Ï IdentifierPart ]
 /*@else [lookahead Ï IdentifierPart ] //@else [lookahead Ï IdentifierPart ]

CCEnd1 ::

 @end [lookahead Ï IdentifierPart ]
 /*@end [lookahead Ï IdentifierPart ] //@end [lookahead Ï IdentifierPart ]

CCSubstitution1 ::

 @ CCSubIdentifier
 /*@ CCSubIdentifier //@ CCSubIdentifier

CCStartMarker ::

 /*@ 
 //@ 

CCEndMarker ::

 @*/ 

CCMultiLineComment1 ::

 /* [lookahead ≠ @ ] MultiLineCommentCharsopt */

SingleLineComment1 ::

 // [lookahead ≠ @] SingleLineCommentCharsopt

CCSubIdentifer ::

  [lookahead Ï CCKeyword ] IdentifierName

CCKeyword ::

 cc_on setifelif 
 elseend

Semantics

If CCInputElementState1 cannot be recognized because there are no remaining characters in source, then Conditional Source processing is completed and the characters of the output supply the Unicode characters for subsequent input element processing. If CCInputElementState1 cannot be recognized and there are characters in source, a SyntaxError exception is thrown.

The productions CCInputElementState1 :: RegularExpressionLiteral, CCInputElementState1 :: StringLiteral, CCInputElementState1 :: CCMultiLineComment1, CCInputElementState1 :: CCSingleLinecomment1, and CCInputElementState1 :: SourceCharacter upon recognition perform the following actions:

  1. Append to the end of output, in left-to-right sequence, the Unicode characters from source that were recognized by the production. Remove the recognized characters from source.

  2. Use CCInputElementState1 to recognize the next input element from source.

The productions CCInputElementState1 :: CCOn, CCInputElementState1 :: CCStartMarker, CCInputElementState1 :: CCEndMarker upon recognition perform the following actions:

  1. Append a <SP> character to the end of output. Remove the recognized characters from source.

  2. Use CCInputElementState1 to recognize the next input element from source.

The production CCInputElementState1 :: CCSet1 upon recognition performs the following actions:

  1. Append a <SP> character to the end of output. Remove the recognized characters from source.

  2. Use CCInputElementStateSetLHS to recognize the next input element from source.

The production CCInputElementState1 :: CCIf1 upon recognition performs the following actions:

  1. Append a <SP> character to the end of output. Remove the recognized characters from source.

  2. Increment the value of IfNestingLevel by 1.

  3. Use CCInputElementStateIfPredicate to recognize the next input element from source.

The production CCInputElementState1 :: CCElif1 upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. If IfNestingLevel is 0, throw a SyntaxError exception.

  3. Use CCInputElementStateFalseIfTail to recognize the next input element from source.

The production CCInputElementState1 :: CCElse1 upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. If IfNestingLevel is 0, throw a SyntaxError exception.

  3. Use CCInputElementStateFalseIfTail to recognize the next input element from source.

The production CCInputElementState1 :: CCEnd upon recognition performs the following actions:

  1. Append a <SP> character to the end of output. Remove the recognized characters from source.

  2. If IfNestingLevel is 0, throw a SyntaxError exception.

  3. Decrement the value of IfNestingLevel by 1.

  4. Use CCInputElementState1 to recognize the next input element from source.

The production CCInputElementState1 :: CCSubstitution1 upon recognition performs the following actions:

  1. Let var be the string of characters recognized as the CCSubIdentifier element of CCSubstitution1.

  2. If the value of var is a key of CCVariables, then let the value be the associated value. Otherwise, let value be the string "NaN".

  3. Let value be ToString(value).

  4. Append the characters of the string value of value to the end of output.

  5. Remove the recognized characters from source.

  6. Use CCInputElementStateIfPredicate to recognize the next input element from source.

Syntax

NOTE:

CCInputElementStateSetLHS is recognized during active conditional processing of the body of an @set statement.

CCInputElementStateSetLHS ::

WhiteSpaceopt @ IdentifierName WhiteSpaceopt = CCExpression

Semantics

If CCInputElementStateSetLHS cannot be recognized a SyntaxError exception is thrown.

The production CCInputElementStateSetLHS :: WhiteSpaceopt @ IdentifierName WhiteSpaceopt = CCExpression upon recognition performs the following actions:

  1. Let setName be the string of characters recognized as the IdentifierName element of CCSubstitution1.

  2. Let value be the result of evaluating CCExpression.

  3. Create an association within CCVariables where the key is the string value of setName and where the value is value. If an association with that key already exists, replace it.

  4. Remove the recognized characters from source.

  5. Use CCInputElementState1 to recognize the next input element from source.

Syntax

NOTE:

CCInputElementStateIfPredicate is recognized during active conditional processing of the predicate portion of an @if or @elif statement.

CCInputElementStateIfPredicate ::

WhiteSpaceopt ( CCExpression WhiteSpaceopt )

Semantics

If CCInputElementStateIfPredicate cannot be recognized, a SyntaxError exception is thrown.

The production CCInputElementStateSetIfPredicate :: WhiteSpaceopt ( CCExpression WhiteSpaceopt ) upon recognition performs the following actions:

  1. Let predicate be the result of evaluating CCExpression.

  2. Increment the value of IfNestingLevel by 1.

  3. Set SkippedIfNestingLevel to 0.

  4. Remove the recognized characters from source.

  5. If ToBoolean(predicate) is true, then use CCInputElementState1 to recognize the next input element from source.

  6. Otherwise, use CCInputElementStateFalseThen to recognize the next input element from source.

Syntax

NOTE:

CCInputElementStateFalseThen is recognized during processing of false clauses of an @if statement for which the true clause has not yet been processed. The current clause may be a "then" clause, an @elif clause, or an @else clause.

CCInputElementStateFalseThen ::

 @if [lookahead Ï IdentifierPart ]
 @elif [lookahead Ï IdentifierPart ]
 @else [lookahead Ï IdentifierPart ]
 @end [lookahead Ï IdentifierPart ]
 SourceCharacter

Semantics

If CCInputElementStateFalseThen cannot be recognized, a SyntaxError exception is thrown.

The production CCInputElementStateFalseThen :: @if [lookahead  IdentifierPart] upon recognition performs the following actions:

  1. Increment the value of SkippedIfNestingLevel by 1.

  2. Remove the recognized characters from source.

  3. Use CCInputElementStateFalseThen to recognize the next input element from source.

The production CCInputElementStateFalseThen :: @elif [lookahead  IdentifierPart] upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. If SkippedIfNestingLevel > 0, then use CCInputElementStateFalseThen to recognize the next input element from source.

  3. Otherwise, use CCInputElementStateIfPredicate to recognize the next input element from source.

The production CCInputElementStateFalseThen :: @else [lookahead  IdentifierPart] upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. If SkippedIfNestingLevel > 0, then use CCInputElementStateFalseThen to recognize the next input element from source.

  3. Otherwise, use CCInputElementState1 to recognize the next input element from source.

The production CCInputElementStateFalseThen :: @end [lookahead  IdentifierPart] upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. If SkippedIfNestingLevel is 0, then go to step 6.

  3. Decrement the value of SkippedIfNestingLevel by 1.

  4. Use CCInputElementStateFalseThen to recognize the next input element from source.

  5. Return.

  6. Decrement the value of IfNestingLevel by 1.

  7. Use CCInputElementState1 to recognize the next input element from source.

The production CCInputElementStateFalseThen :: SourceCharacter upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. Use CCInputElementStateFalseThen to recognize the next input element from source.

Syntax

NOTE:

CCInputElementStateFalseThen is recognized during processing of false clauses of an @if statement for which the true clause has already been processed. It is also used during processing of all clauses of a @if statement that is nested within a false clause of an enclosing @if statement. The current clause may be a "then" clause, an @elif clause or an @else clause.

CCInputElementStateFalseIfTail ::

 @if [lookahead Ï IdentifierPart ]
 @elif [lookahead Ï IdentifierPart ]
 @else [lookahead Ï IdentifierPart ]
 @end [lookahead Ï IdentifierPart ]
 SourceCharacter

Semantics

If CCInputElementStateFalseIfTail cannot be recognized, a SyntaxError exception is thrown.

The production CCInputElementStateFalseIfTail :: @if [lookahead  IdentifierPart] upon recognition performs the following actions:

  1. Increment the value of SkippedIfNestingLevel by 1.

  2. Remove the recognized characters from source.

  3. Use CCInputElementStateFalseIfTail to recognize the next input element from source.

The productions CCInputElementStateFalseIfTail :: @elif [lookahead  IdentifierPart] and CCInputElementStateFalseIfTail :: @else [lookahead  IdentifierPart] upon recognition perform the following actions:

  1. Remove the recognized characters from source.

  2. Use CCInputElementStateFalseIfTail to recognize the next input element from source.

The production CCInputElementStateFalseIfTail :: @end [lookahead  IdentifierPart] upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. If SkippedIfNestingLevel is 0, then go to step 6.

  3. Decrement the value of SkippedIfNestingLevel by 1.

  4. Use CCInputElementStateFalseIfTail to recognize the next input element from source.

  5. Return.

  6. Decrement the value of IfNestingLevel by 1.

  7. Use CCInputElementState1 to recognize the next input element from source.

The production CCInputElementStateFalseIfTail :: SourceCharacter upon recognition performs the following actions:

  1. Remove the recognized characters from source.

  2. Use CCInputElementStateFalseIfTail to recognize the next input element from source.

Syntax

CCExpression ::

                 CCLogicalANDExpression                CCExpression WhiteSpaceopt  || CCLogicalANDExpression

CCLogicalANDExpression ::

 CCBitwiseORExpressionCCcLogicalANDExpression  WhiteSpaceopt  &&  CCBitwiseORExpression           

CCBitwiseORExpression ::

 CCBitwiseXORExpressionCCBitwiseORExpression  WhiteSpaceopt  | CCBitwiseXORExpression

CCBitwiseXORExpression ::

 CCBitwiseANDExpressionCCBitwiseXORExpression  WhiteSpaceopt ^ CCBitwiseANDExpression

CCBitwiseANDExpression ::

 CCEqualityExpressionCCBitwiseANDExpression  WhiteSpaceopt & CCEqualityExpression

CCEqualityExpression ::

 CCRelationalExpressionCCEqualityExpression  WhiteSpaceopt == CCRelationalExpressionCCEqualityExpression  WhiteSpaceopt!= CCRelationalExpressionCCEqualityExpression WhiteSpaceopt === CCRelationalExpressionCCEqualityExpression  WhiteSpaceopt !== CCRelationalExpression

CCRelationalExpression ::

 CCShiftExpressionCCRelationalExpression  WhiteSpaceopt < CCShiftExpressionCCRelationalExpression  WhiteSpaceopt > CCShiftExpressionCCRelationalExpression WhiteSpaceopt <= CCShiftExpressionCCRelationalExpression  WhiteSpaceopt >= CCShiftExpression

CCShiftExpression ::

 CCAdditiveExpressionCCShiftExpression  WhiteSpaceopt << CCAdditiveExpressionCCShiftExpression  WhiteSpaceopt >> CCAdditiveExpressionCCShiftExpression  WhiteSpaceopt >>> CCAdditiveExpression

CCAdditiveExpression ::

 CCMultiplicativeExpressionCCAdditiveExpression  WhiteSpaceopt + CCMultiplicativeExpressionCCAdditiveExpression  WhiteSpaceopt – CCMultiplicativeExpression

CCMultiplicativeExpression ::

 CCUnaryExpressionCCMultiplicativeExpression  WhiteSpaceopt * CCUnaryExpressionCCMultiplicativeExpression  WhiteSpaceopt / CCUnaryExpressionCCMultiplicativeExpression  WhiteSpaceopt % CCUnaryExpression

UnaryExpression ::

 CCPrimaryExpressionWhiteSpaceopt + CCUnaryExpressionWhiteSpaceopt - CCUnaryExpressionWhiteSpaceopt ~ CCUnaryExpressionWhiteSpaceopt! CCUnaryExpression

CCPrimaryExpression ::

 CCVariableCCLiteralWhiteSpaceopt ( Expression )

CCLiteral ::

 WhiteSpaceopt true [lookahead Ï IdentifierPart ] WhiteSpaceopt false [lookahead Ï IdentifierPart ] WhiteSpaceopt Infinity [lookahead Ï IdentifierPart ]
 WhiteSpaceopt NumericLiteral

CCVariable ::

 WhiteSpaceopt @ IdentifierName

Semantics

Unless otherwise specified in this section, the productions of CCExpression are evaluated using the same semantic rules as the analogous productions of the ECMAScript syntactic grammar for Expression in [ECMA-262/5] section 11. However, only values of types Number and Boolean can occur during the evaluation of CCExpression productions, so any semantic steps that are relative to other types of values are not relevant.

The production CCLiteral :: WhiteSpaceopt true [lookahead  IdentifierPart] is evaluated by returning the value true.

The production CCLiteral :: WhiteSpaceopt false [lookahead  IdentifierPart] is evaluated by returning the value false.

The production CCLiteral :: WhiteSpaceopt Infinity [lookahead  IdentifierPart] is evaluated by returning the value +∞.

The production CCVariable :: WhiteSpaceopt  @ IdentifierName is evaluated by performing the following steps:

  1. Let var be the string of characters recognized as the IdentifierName element of CCVariable.

  2. If the value of var is a key of CCVariables, then let value be the associated value. Otherwise, let value be "NaN".

  3. Return value.