파일이 어휘적으로 분석되면 여러 종류의 원본 전처리가 발생합니다. 가장 중요한 조건부 컴파일은 구문 문법에 의해 처리되는 원본을 결정합니다. 외부 소스 지시문과 지역 지시문이라는 두 가지 다른 유형의 지시문은 원본에 대한 메타 정보를 제공하지만 컴파일에는 영향을 주지 않습니다.
조건부 컴파일
조건부 컴파일은 논리 줄 시퀀스가 실제 코드로 변환되는지 여부를 제어합니다. 조건부 컴파일이 시작될 때 모든 논리 줄이 활성화됩니다. 그러나 조건부 컴파일 문에 줄을 묶으면 파일 내에서 해당 줄을 선택적으로 사용하지 않도록 설정하여 나머지 컴파일 프로세스 중에 해당 줄이 무시될 수 있습니다.
CCStart
: CCStatement*
;
CCStatement
: CCConstantDeclaration
| CCIfGroup
| LogicalLine
;
CCExpression
: LiteralExpression
| CCParenthesizedExpression
| CCSimpleNameExpression
| CCCastExpression
| CCOperatorExpression
| CCConditionalExpression
;
CCParenthesizedExpression
: '(' CCExpression ')'
;
CCSimpleNameExpression
: Identifier
;
CCCastExpression
: 'DirectCast' '(' CCExpression ',' TypeName ')'
| 'TryCast' '(' CCExpression ',' TypeName ')'
| 'CType' '(' CCExpression ',' TypeName ')'
| CastTarget '(' CCExpression ')'
;
CCOperatorExpression
: CCUnaryOperator CCExpression
| CCExpression CCBinaryOperator CCExpression
;
CCUnaryOperator
: '+' | '-' | 'Not'
;
CCBinaryOperator
: '+' | '-' | '*' | '/' | '\\' | 'Mod' | '^' | '='
| '<' '>' | '<' | '>' | '<' '=' | '>' '=' | '&'
| 'And' | 'Or' | 'Xor' | 'AndAlso' | 'OrElse'
| '<' '<' | '>' '>'
;
CCConditionalExpression
: 'If' '(' CCExpression ',' CCExpression ',' CCExpression ')'
| 'If' '(' CCExpression ',' CCExpression ')'
;
예를 들어 프로그램
#Const A = True
#Const B = False
Class C
#If A Then
Sub F()
End Sub
#Else
Sub G()
End Sub
#End If
#If B Then
Sub H()
End Sub
#Else
Sub I()
End Sub
#End If
End Class
는 프로그램과 정확히 동일한 토큰 시퀀스를 생성합니다.
Class C
Sub F()
End Sub
Sub I()
End Sub
End Class
조건부 컴파일 지시문에서 허용되는 상수 식은 일반 상수 식의 하위 집합입니다.
전처리기는 모든 토큰 전후에 공백 및 명시적 줄 연속을 허용합니다.
조건부 상수 지시문
조건부 상수 문은 소스 파일로 범위가 지정된 별도의 조건부 컴파일 선언 공간에 존재하는 상수를 정의합니다.
CCConstantDeclaration
: '#' 'Const' Identifier '=' CCExpression LineTerminator
;
조건부 컴파일 상수에 대한 명시적 선언이 필요하지 않으며 조건부 컴파일 지시문에서 조건부 상수는 암시적으로 정의할 수 있으므로 선언 공간은 특별합니다.
값을 할당하기 전에 조건부 컴파일 상수에 값 Nothing이 있습니다. 조건부 컴파일 상수에 상수 식이어야 하는 값이 할당되면 상수의 형식이 할당되는 값의 형식이 됩니다. 조건부 컴파일 상수는 소스 파일 전체에서 여러 번 다시 정의될 수 있습니다.
예를 들어 다음 코드는 문자열 about to print value 과 값 Test만 인쇄합니다.
Module M1
Sub PrintValue(Test As Integer)
#Const DebugCode = True
#If DebugCode Then
Console.WriteLine("about to print value")
#End If
#Const DebugCode = False
Console.WriteLine(Test)
#If DebugCode Then
Console.WriteLine("printed value")
#End If
End Sub
End Module
컴파일 환경은 조건부 컴파일 선언 공간에서 조건부 상수도 정의할 수 있습니다.
조건부 컴파일 지시문
조건부 컴파일 지시문은 조건부 컴파일을 제어합니다.
CCIfGroup
: '#' 'If' CCExpression 'Then'? LineTerminator CCStatement*
CCElseIfGroup* CCElseGroup? '#' 'End' 'If' LineTerminator
;
CCElseIfGroup
: '#' ElseIf CCExpression 'Then'? LineTerminator CCStatement*
;
CCElseGroup
: '#' 'Else' LineTerminator CCStatement*
;
조건부 상수는 상수 식과 조건부 컴파일 상수만 참조할 수 있습니다. 단일 조건부 컴파일 그룹 내의 각 상수 식이 계산되고 조건식 중 하나가 계산될 때까지 텍스트 순서로 형식으로 변환 Boolean 됩니다 True. 식을 변환할 수 Boolean없는 경우 컴파일 시간 오류가 발생합니다. 허용되는 의미 체계 및 이진 문자열 비교는 지시문 또는 컴파일 환경 설정에 관계없이 Option 조건부 컴파일 상수 식을 평가할 때 항상 사용됩니다.
중첩된 조건부 컴파일 지시문을 포함하여 그룹으로 묶인 모든 줄은 식을 포함하는 True 문과 그룹의 다음 조건문 사이의 줄 또는 그룹에 나타나고 모든 식이 계산False되는 경우 Else 문과 End If 문 사이의 Else 줄을 제외하고 비활성화됩니다.
이 예제에서는 주변 Debug 조건부 컴파일 지시문이 계산False되기 때문에 조건부 컴파일 지시문의 호출 WriteToLogTrace 이 처리되지 않습니다.
#Const Debug = False ' Debugging off
#Const Trace = True ' Tracing on
Class PurchaseTransaction
Sub Commit()
#If Debug Then
CheckConsistency()
#If Trace Then
WriteToLog(Me.ToString())
#End If
#End If
...
End Sub
End Class
외부 원본 지시문
원본 파일에는 원본 줄과 원본 외부 텍스트 간의 매핑을 나타내는 외부 소스 지시문이 포함될 수 있습니다.
ESDStart
: ExternalSourceStatement*
;
ExternalSourceStatement
: ExternalSourceGroup
| LogicalLine
;
ExternalSourceGroup
: '#' 'ExternalSource' '(' StringLiteral ',' IntLiteral ')' LineTerminator
LogicalLine* '#' 'End' 'ExternalSource' LineTerminator
;
외부 소스 지시문은 컴파일에 영향을 주지 않으며 중첩되지 않을 수 있습니다. 다음은 그 예입니다.
Module Test
Sub Main()
#ExternalSource("c:\wwwroot\inetpub\test.aspx", 30)
Console.WriteLine("In test.aspx")
#End ExternalSource
End Sub
End Module
지역 지시문
지역 지시문은 소스 코드 줄을 그룹화하지만 컴파일에는 다른 영향을 주지 않습니다. IDE(통합 개발 환경)에서 전체 그룹을 축소 및 숨기거나 확장 및 볼 수 있습니다.
RegionStart
: RegionStatement*
;
RegionStatement
: RegionGroup
| LogicalLine
;
RegionGroup
: '#' 'Region' StringLiteral LineTerminator
RegionStatement*
'#' 'End' 'Region' LineTerminator
;
영역은 중첩될 수 있습니다. 영역 지시문은 메서드 본문 내에서 시작하거나 종료할 수 없으며 프로그램의 블록 구조를 준수해야 한다는 점에서 특별합니다. 다음은 그 예입니다.
Module Test
#Region "Startup code - do not edit"
Sub Main()
End Sub
#End Region
End Module
' Error due to Region directives breaking the block structure
Class C
#Region "Fred"
End Class
#End Region
외부 체크섬 지시문
원본 파일에는 외부 소스 지시문에서 참조되는 파일에 대해 내보내야 하는 체크섬을 나타내는 외부 체크섬 지시문이 포함될 수 있습니다. 다른 모든 측면에서 외부 소스 지시문은 컴파일에 영향을 주지 않습니다.
ExternalChecksumStart
: ExternalChecksumStatement*
;
ExternalChecksumStatement
: '#' 'ExternalChecksum' '('
StringLiteral ',' StringLiteral ',' StringLiteral
')' LineTerminator
;
외부 체크섬 지시문에는 외부 파일의 파일 이름, 파일과 연결된 GUID(Globally Unique Identifier) 및 파일에 대한 체크섬이 포함됩니다. GUID는 "{xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxxx}" 형식의 문자열 상수로 지정됩니다. 여기서 x는 16진수입니다. 체크섬은 "xxxx..."형식의 문자열 상수로 지정됩니다. 여기서 x는 16진수입니다. 체크섬의 숫자 수는 짝수여야 합니다.
모든 GUID 및 체크섬 값이 정확하게 일치하는 경우 외부 파일에는 여러 개의 외부 체크섬 지시문이 연결되어 있을 수 있습니다. 외부 파일의 이름이 컴파일되는 파일의 이름과 일치하면 컴파일러의 체크섬 계산을 위해 체크섬이 무시됩니다.
다음은 그 예입니다.
#ExternalChecksum("c:\wwwroot\inetpub\test.aspx", _
"{12345678-1234-1234-1234-123456789abc}", _
"1a2b3c4e5f617239a49b9a9c0391849d34950f923fab9484")
Module Test
Sub Main()
#ExternalSource("c:\wwwroot\inetpub\test.aspx", 30)
Console.WriteLine("In test.aspx")
#End ExternalSource
End Sub
End Module
Visual Basic language spec