📄 conditionalexpression.vb
字号:
'
' Visual Basic.Net Compiler
' Copyright (C) 2004 - 2007 Rolf Bjarne Kvinge, RKvinge@novell.com
'
' This library is free software; you can redistribute it and/or
' modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation; either
' version 2.1 of the License, or (at your option) any later version.
'
' This library is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
' Lesser General Public License for more details.
'
' You should have received a copy of the GNU Lesser General Public
' License along with this library; if not, write to the Free Software
' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
'
Option Compare Text
Public Class ConditionalExpression
Inherits BaseObject
Private m_Compiler As ConditionalCompiler
<Obsolete()> Friend Overrides ReadOnly Property tm() As tm
Get
Return MyBase.tm 'Throw New InternalException("Don't use this")
End Get
End Property
ReadOnly Property CurrentConstants() As ConditionalConstants
Get
Return m_Compiler.CurrentConstants
End Get
End Property
Public Sub New(ByVal Compiler As ConditionalCompiler)
MyBase.New(Compiler)
m_Compiler = Compiler
End Sub
ReadOnly Property Reader() As ITokenReader
Get
Return m_Compiler.Reader
End Get
End Property
Function RuleIdentifier(ByRef Result As Object) As Boolean
'A value of 0 evaluates as false, anything else as true
If Reader.Peek.Equals(KS.Nothing) Then
Result = Nothing
Reader.Next()
ElseIf Reader.Peek.IsLiteral Then
Dim tp As TypeCode = Type.GetTypeCode(Reader.Peek.LiteralValue.GetType)
Select Case tp
Case TypeCode.String
Result = Reader.Peek.StringLiteral
Case TypeCode.Object
Throw New InternalException("Shouldn't happen, Nothing is a keyword.")
Case TypeCode.Boolean
Throw New InternalException("Shouldn't happen, True and False are keywords.")
Case TypeCode.DateTime
Result = Reader.Peek.DateLiteral
Case Else
Helper.Assert(Compiler.TypeResolution.IsNumericType(Reader.Peek.LiteralValue.GetType))
Result = CDbl(Reader.Peek.LiteralValue) 'AsFloatingPointLiteral.Literal
End Select
'Result = CurrentToken.Value.Literal
Reader.Next()
ElseIf Reader.Peek.IsKeyword Then
Dim tpType As Type = Compiler.TypeResolution.KeywordToType(Reader.Peek.Keyword)
If tpType Is Nothing Then
If Reader.Peek.Equals(KS.True) Then
Result = True
Reader.Next()
Return True
ElseIf Reader.Peek.Equals(KS.False) Then
Result = False
Reader.Next()
Return True
Else 'TODO: Conversion functions (CInt...)
Compiler.Report.ShowMessage(Messages.VBNC30201)
End If
Reader.Next()
Return False
Else
'A builtin type, i.e:
'#Const a = Integer.MaxValue
'#Const a = (user defined type).Constant is not allowed.
Throw New InternalException("") 'TODO
End If
ElseIf Reader.Peek.IsIdentifier Then
'Find the identifier in the list of defines.
If CurrentConstants.ContainsKey(Reader.Peek.Identifier) Then
Result = CurrentConstants.Item(Reader.Peek.Identifier).Value
Reader.Next()
Else
Result = Nothing
Reader.Next()
End If
End If
Return True
End Function
Function RuleExponent(ByRef Result As Object) As Boolean
Dim LSide As Object = Nothing, RSide As Object = Nothing
If RuleIdentifier(LSide) = False Then Return False
While Reader.Peek.Equals(KS.Power)
Reader.Next()
RuleExpression(RSide)
Dim op1, op2 As Double
Dim bErr As Boolean
If ToDouble(LSide, op1) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, LSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
If ToDouble(RSide, op2) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, RSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
If bErr Then
LSide = CDbl(0)
Else
LSide = op1 ^ op2
End If
End While
Result = LSide
Return True
End Function
Function RuleUnaryNegation(ByRef Result As Object) As Boolean
Dim LSide As Object = Nothing
If Reader.Peek.Equals(KS.Minus) Then
Reader.Next()
RuleUnaryNegation = RuleExponent(LSide)
Dim op1 As Double
If ToDouble(LSide, op1) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, LSide.GetType.ToString, KS.Double.ToString)
LSide = 0
Else
LSide = -op1
End If
Else
If RuleExponent(LSide) = False Then
Return False
End If
End If
Result = LSide
Return True
End Function
Function RuleMultiplicationAndRealDivision(ByRef Result As Object) As Boolean
Dim LSide As Object = Nothing, RSide As Object = Nothing
If RuleUnaryNegation(LSide) = False Then Return False
While Reader.Peek.Equals(KS.Mult, KS.RealDivision)
Dim DoMult As Boolean
DoMult = Reader.Peek.Equals(KS.Mult)
Reader.Next()
RuleExpression(RSide)
Dim op1, op2 As Double
Dim bErr As Boolean
If ToDouble(LSide, op1) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, LSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
If ToDouble(RSide, op2) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, RSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
If bErr Then
LSide = CDbl(0)
ElseIf DoMult Then
LSide = op1 * op2
Else
If op2 = 0 Then
Compiler.Report.ShowMessage(Messages.VBNC30542)
LSide = CDbl(0)
Else
LSide = op1 / op2
End If
End If
End While
Result = LSide
Return True
End Function
Function RuleIntegerDivision(ByRef Result As Object) As Boolean
Dim LSide As Object = Nothing, RSide As Object = Nothing
If RuleMultiplicationAndRealDivision(LSide) = False Then Return False
While Reader.Peek.Equals(KS.IntDivision)
Reader.Next()
RuleExpression(RSide)
Dim op1, op2 As Double
Dim bErr As Boolean
If ToDouble(LSide, op1) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, LSide.GetType.ToString, KS.Long.ToString)
bErr = True
End If
If ToDouble(RSide, op2) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, RSide.GetType.ToString, KS.Long.ToString)
bErr = True
End If
If bErr Then
LSide = CDbl(0)
ElseIf CLng(op2) = 0 Then
Compiler.Report.ShowMessage(Messages.VBNC30542)
LSide = CDbl(0)
Else
LSide = CDbl(CLng(op1) \ CLng(op2))
End If
End While
Result = LSide
Return True
End Function
Function RuleMod(ByRef Result As Object) As Boolean
Dim LSide As Object = Nothing, RSide As Object = Nothing
If RuleIntegerDivision(LSide) = False Then Return False
While Reader.Peek.Equals(KS.Mod)
Reader.Next()
RuleExpression(RSide)
Dim op1, op2 As Double
Dim bErr As Boolean
If ToDouble(LSide, op1) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, LSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
If ToDouble(RSide, op2) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, RSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
If bErr Then
LSide = CLng(0)
Else
LSide = op1 Mod op2
End If
End While
Result = LSide
Return True
End Function
Function RuleAdditionSubtractionStringConcat(ByRef Result As Object) As Boolean
Dim LSide As Object = Nothing, RSide As Object = Nothing
If RuleMod(LSide) = False Then Return False
While Reader.Peek.Equals(KS.Minus, KS.Add)
Dim DoAdd As Boolean
DoAdd = Reader.Peek.Equals(KS.Add)
Reader.Next()
RuleExpression(RSide)
Dim bErr As Boolean
If TypeOf LSide Is String AndAlso TypeOf RSide Is String Then
'String concat
LSide = CStr(LSide) & CStr(RSide)
Else
Dim op1, op2 As Double
If TypeOf LSide Is String Then
op1 = Double.Parse(DirectCast(LSide, String))
If ToDouble(RSide, op2) = False Then
Compiler.Report.ShowMessage(Messages.VBNC30748, RSide.GetType.ToString, KS.Double.ToString)
bErr = True
End If
ElseIf TypeOf RSide Is String Then
op2 = Double.Parse(DirectCast(RSide, String))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -