1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| Option Explicit
Private fLexer As New CLexer
Private Property Get CurrentToken() As TokenType
CurrentToken = fLexer.CurrToken
End Property
Private Function NextToken() As TokenType
NextToken = fLexer.NextToken
SynErr fLexer.CurrToken = tkInvalid
End Function
Private Function IsUnairyOp(ByVal AOP As TokenType) As Boolean
Select Case AOP
Case tkOpNot, tkOpPlus, tkOpMinus
IsUnairyOp = True
End Select
End Function
Private Function IsFacOperator(ByVal AOP As TokenType) As Boolean
IsFacOperator = ((AOP > OpFacBegin) And (AOP < OpFacEnd))
End Function
Private Function IsTermOperator(ByVal AOP As TokenType) As Boolean
IsTermOperator = ((AOP > OpTermBegin) And (AOP < OpTermEnd))
End Function
'<Factor> ::= (+|-)<Expression>| NUMBER | <Simple Call> | CONSTANT |'('<Expression>')' | '['<Expression>']' | NULL
Private Function GetFactor() As Double
Dim UOP As TokenType
Dim Ret As Double
Dim Ident As String
If IsUnairyOp(NextToken) Then
UOP = CurrentToken
Ret = GetExpression()
UnairyOperation UOP, Ret
Else
Select Case CurrentToken
Case tkNumber
Ret = CDbl(fLexer.Token)
Case tkIdent
Ident = fLexer.Token
If Not GetConstValue(Ret, Ident) Then
SynErr NextToken <> tkOpenExp
Ret = Simple_Call(GetExpression, Ident)
SynErr CurrentToken <> tkCloseExp
End If
Case tkOpenExp
Ret = GetExpression
SynErr CurrentToken <> tkCloseExp
Case tkOpenBra
Ret = GetExpression
SynErr CurrentToken <> tkCloseBra
Case tkNone
Ret = 0
Case Else
SynErr
End Select
NextToken
End If
GetFactor = Ret
End Function
'<Exp> ::= <Factor>(^<Factor>)*
Private Function GetExp() As Double
GetExp = GetFactor
While CurrentToken = tkOpPow
BinaryOperation CurrentToken, GetExp, GetFactor
Wend
End Function
'<Term> ::= <Exp> (DIV | * | / | MOD ... <Exp>)*
Private Function GetTerm() As Double
GetTerm = GetExp
While IsFacOperator(CurrentToken)
BinaryOperation CurrentToken, GetTerm, GetExp
Wend
End Function
'<Expression> ::= <Term> (+|- ... <Term>)*
Private Function GetExpression() As Double
GetExpression = GetTerm
While IsTermOperator(CurrentToken)
BinaryOperation CurrentToken, GetExpression, GetTerm
Wend
End Function
'<Simple Call> ::= (SIN|COS|SQR|EXP|LOG ...)
Private Function Simple_Call(Value As Double, ByVal AFuncName As String) As Double
Select Case AFuncName
Case "SIN": Simple_Call = Sin(Value)
Case "COS": Simple_Call = Cos(Value)
Case "SQR": Simple_Call = Sqr(Value)
Case "EXP": Simple_Call = Exp(Value)
Case "LOG": Simple_Call = Log(Value)
Case Else
SynErr
End Select
End Function
'<Const> ::= (PI|...)
Private Function GetConstValue(Value As Double, ByVal AConstName As String) As Boolean
GetConstValue = True
Select Case AConstName
Case "PI": Value = 3.14159265358979
Case Else
GetConstValue = False
End Select
End Function
Private Sub UnairyOperation(ByVal OP As TokenType, Value As Double)
Select Case OP
Case tkOpMinus: Value = -Value
Case tkOpNot: Value = Not Value
Case tkOpPlus: Value = Value
Case Else
SynErr
End Select
End Sub
Private Sub BinaryOperation(ByVal OP As TokenType, Value1 As Double, Value2 As Double)
Select Case OP
Case tkOpPlus: Value1 = Value1 + Value2
Case tkOpMinus: Value1 = Value1 - Value2
Case tkOpMul: Value1 = Value1 * Value2
Case tkOpDivF: Value1 = Value1 / Value2
Case tkOpDiv: Value1 = Value1 \ Value2
Case tkOpMod: Value1 = Value1 Mod Value2
Case tkOpOr: Value1 = Value1 Or Value2
Case tkOpAnd: Value1 = Value1 And Value2
Case tkOpXor: Value1 = Value1 Xor Value2
Case tkOpPow: Value1 = Value1 ^ Value2
Case tkOpShl: Value1 = Value1 * (2 * Value2)
Case tkOpShr: Value1 = Value1 \ (2 * Value2)
Case Else
SynErr
End Select
End Sub
Public Function EvalExp(ByVal Text As String) As Double
fLexer.Text = Text
EvalExp = GetExpression
SynErr CurrentToken <> tkNone
End Function
Private Sub SynErr(Optional ByVal ARaise As Boolean = True)
If ARaise Then
Err.Description = "Erreur d'évaluation à la position " & CStr(fLexer.Position)
Err.Raise 1001
End If
End Sub |
Partager