|
|

楼主 |
发表于 2008-4-6 09:51:00
|
显示全部楼层
Re:NFA的3种编码优劣,你喜欢怎么做?JAVA去掉了goto你喜欢吗?
翻看Kashier代码,实际上我用了2个词法分析机。一次是找出 [] 中的数字,但不判断是否为合法的time。
这么做是有原因的。因为同样允许用户按 F5 在 "Go" 对话框里输入time字符串。
找出了[]中的数字之后,填写到 Go 对话框里,然后进行时间值的分析。
'找出光标附近的中的数字位置的图灵机。
Public Sub btGo_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
gFrmMain.txKashi.SetFocus
If Not (x >= 0 And x <= btGo.Width And y >= 0 And y <= btGo.Height) Then Exit Sub
If Not gMedia.GetIsOpened Then Exit Sub
If (Button And 1) = 0 Then Exit Sub
Dim txKashi As RichTextBox
Set txKashi = gKashi.GettxKashi
Dim ascii As Integer
Dim i As Long
i = txKashi.SelStart + 1
Dim leng As Long
leng = Len(txKashi.text)
Dim state As Integer
state = 0
Dim LArcPos As Long, RArcPos As Long
Dim IsSeccessful As Boolean
Dim counter As Long
Do
If i >= 1 And i <= leng Then
ascii = Asc(Mid(txKashi.text, i))
End If
If state = 0 Then
If i < 1 Then 'head
IsSeccessful = False
Exit Do
ElseIf i > leng Then 'end
state = 3
i = i - 1
GoTo Continue
ElseIf (ascii >= CHAR_0 And ascii <= CHAR_9) Or ascii = CHAR_DOT Or ascii = CHAR_COLON Then
i = i - 1
GoTo Continue
ElseIf ascii = CHAR_LARC Then
LArcPos = i
state = 1
i = i + 1
GoTo Continue
ElseIf ascii = CHAR_RARC Then
RArcPos = i
state = 2
i = i - 1
GoTo Continue
ElseIf ascii = 10 Or ascii = 13 Then
state = 3
i = i - 1
GoTo Continue
Else
state = 3
i = i - 1
GoTo Continue
End If
ElseIf state = 1 Then
If i > leng Then 'end
state = 3
i = i - 2
GoTo Continue
ElseIf (ascii >= CHAR_0 And ascii <= CHAR_9) Or ascii = CHAR_DOT Or ascii = CHAR_COLON Then
i = i + 1
GoTo Continue
ElseIf ascii = CHAR_LARC Then
state = 3
i = i - 2
GoTo Continue
ElseIf ascii = CHAR_RARC Then
RArcPos = i
IsSeccessful = True
Exit Do
ElseIf ascii = 10 Or ascii = 13 Then
state = 3
i = i - 2
GoTo Continue
Else
state = 3
i = i - 2
GoTo Continue
End If
ElseIf state = 2 Then
If i < 1 Then 'head
IsSeccessful = False
Exit Do
ElseIf (ascii >= CHAR_0 And ascii <= CHAR_9) Or ascii = CHAR_DOT Or ascii = CHAR_COLON Then
i = i - 1
GoTo Continue
ElseIf ascii = CHAR_LARC Then
LArcPos = i
IsSeccessful = True
Exit Do
ElseIf ascii = CHAR_RARC Then
RArcPos = i
i = i - 1
GoTo Continue
ElseIf ascii = 10 Or ascii = 13 Then
IsSeccessful = False
Exit Do
Else
state = 3
i = i - 1
GoTo Continue
End If
ElseIf state = 3 Then
If i < 1 Then 'head
IsSeccessful = False
Exit Do
ElseIf (ascii >= CHAR_0 And ascii <= CHAR_9) Or ascii = CHAR_DOT Or ascii = CHAR_COLON Then
i = i - 1
GoTo Continue
ElseIf ascii = CHAR_LARC Then
i = i - 1
GoTo Continue
ElseIf ascii = CHAR_RARC Then
RArcPos = i
state = 2
i = i - 1
GoTo Continue
ElseIf ascii = 10 Or ascii = 13 Then
IsSeccessful = False
Exit Do
Else
i = i - 1
GoTo Continue
End If
End If
Continue:
counter = counter + 1
If counter > 9999 Then
IsSeccessful = False
Exit Do
End If
Loop
Dim tmp As String
If IsSeccessful Then
tmp = Mid(txKashi.text, LArcPos + 1, (RArcPos - 1) - (LArcPos + 1) + 1)
End If
Dim ret As Boolean
Dim pSeconds As Double
If (Shift And KEYSHIFT) = 0 Then
ret = gFrmInputTime.InputTime(tmp, pSeconds)
If Not ret Then Exit Sub 'canceled by user by such pressing Esc
Else
If tmp = "" Then Exit Sub '???s???????e?L?X?g???????
pSeconds = TimeToSeconds(tmp)
If pSeconds = TIMETEXT_ILLEGAL Then Exit Sub
End If
gMedia.SeekMedia pSeconds
mLastTime = gMedia.GetCrrtPos
End Sub
'分析时间字符串用的是下面的代码(完整的!)用了个NFA
Attribute VB_Name = "TimeCalc"
Option Explicit
Public Const CHAR_0 = 48 ' 0
Public Const CHAR_9 = 57 '9
Public Const CHAR_DOT = 46 ' .
Public Const CHAR_COLON = 58 ' :
Public Const CHAR_LARC = 91 ' [
Public Const CHAR_RARC = 93 ' ]
Public Const TIMETEXT_ILLEGAL = -1
Private Type WORD
wVal As String
wType As Integer
End Type
Private Const WTYPE_HMS = 1 'number of hour/min/second
Private Const WTYPE_MS = 2 'millisecond
Private Const WTYPE_E = 3 '??
Private Const WTYPE_ERROR = 4
Public Function SecondsToTime(sec As Double, houred As Boolean, msn As Byte) As String
Dim intsec As Long
Dim ms As String
Dim s As Long
Dim h As Long
Dim m As Long
Dim tmp As Long
intsec = Int(sec)
h = Int(intsec / 3600)
tmp = intsec Mod 3600
m = Int(tmp / 60)
s = tmp Mod 60
If h > 0 Or houred Then
SecondsToTime = Format(h, "00") + ":"
End If
SecondsToTime = SecondsToTime + Format(m, "00") + ":" + Format(s, "00")
If msn > 0 Then
ms = Format(sec - intsec, "." + String(msn, "0"))
If Left(ms, 1) <> "." Then '?@format?????????????P?D?O?O????I
ms = "." + String(msn, "9") ' ????l??h.999?h????B
End If
SecondsToTime = SecondsToTime + ms
End If
End Function
Public Function TimeToSeconds(text As String) As Double
Dim index As Integer
index = 1
Dim tmp(1 To 4) As WORD
If index > Len(text) Then
TimeToSeconds = 0
Exit Function
End If
tmp(1) = GetWord(text, index)
If tmp(1).wType = WTYPE_ERROR Then
TimeToSeconds = TIMETEXT_ILLEGAL
Exit Function
End If
If index > Len(text) Then
If tmp(1).wType = WTYPE_HMS Then
TimeToSeconds = CDbl(tmp(1).wVal)
Exit Function
ElseIf tmp(1).wType = WTYPE_MS Then
TimeToSeconds = CDbl("0." + tmp(1).wVal)
Exit Function
ElseIf tmp(1).wType = WTYPE_E Then
TimeToSeconds = 0
Exit Function
End If
End If
tmp(2) = GetWord(text, index)
If tmp(2).wType = WTYPE_ERROR Then
TimeToSeconds = TIMETEXT_ILLEGAL
Exit Function
End If
If index > Len(text) Then
If tmp(2).wType = WTYPE_HMS Then
TimeToSeconds = CDbl(tmp(1).wVal) * 60 + CDbl(tmp(2).wVal)
Exit Function
ElseIf tmp(2).wType = WTYPE_MS Then
TimeToSeconds = CDbl(tmp(1).wVal + "." + tmp(2).wVal)
Exit Function
End If
End If
tmp(3) = GetWord(text, index)
If tmp(3).wType = WTYPE_ERROR Then
TimeToSeconds = TIMETEXT_ILLEGAL
Exit Function
End If
If index > Len(text) Then
If tmp(3).wType = WTYPE_HMS Then
TimeToSeconds = CDbl(tmp(1).wVal) * 3600 + CDbl(tmp(2).wVal) * 60 + CDbl(tmp(3).wVal)
Exit Function
ElseIf tmp(3).wType = WTYPE_MS Then
TimeToSeconds = CDbl(tmp(1).wVal) * 60 + CDbl(tmp(2).wVal + "." + tmp(3).wVal)
Exit Function
End If
End If
tmp(4) = GetWord(text, index)
If tmp(4).wType = WTYPE_ERROR Then
TimeToSeconds = TIMETEXT_ILLEGAL
Exit Function
End If
If index > Len(text) Then
If tmp(4).wType = WTYPE_HMS Then
TimeToSeconds = TIMETEXT_ILLEGAL
Exit Function
ElseIf tmp(4).wType = WTYPE_MS Then
TimeToSeconds = CDbl(tmp(1).wVal) * 3600 + CDbl(tmp(2).wVal) * 60 + CDbl(tmp(3).wVal + "." + tmp(4).wVal)
Exit Function
End If
End If
End Function
Private Function GetWord(ByRef pStr As String, ByRef pIndex As Integer) As WORD
Dim state As Integer
Dim char As String * 1
Dim ascii As Integer
state = 0
GetWord.wVal = ""
Do
If pIndex <= Len(pStr) Then
char = Mid(pStr, pIndex)
ascii = Asc(char)
End If
Select Case state
Case 0:
If pIndex > Len(pStr) Then
GetWord.wType = WTYPE_E
Exit Function
ElseIf ascii >= CHAR_0 And ascii <= CHAR_9 Then
GetWord.wVal = GetWord.wVal + char
state = 1
GoTo Continue
ElseIf ascii = CHAR_DOT Then
state = 4
GoTo Continue
ElseIf ascii = CHAR_COLON Then
state = 2
GoTo Continue
Else
GetWord.wType = WTYPE_ERROR
Exit Function
End If
Case 1:
If pIndex > Len(pStr) Then
GetWord.wType = WTYPE_HMS
Exit Function
ElseIf ascii >= CHAR_0 And ascii <= CHAR_9 Then
GetWord.wVal = GetWord.wVal + char
GoTo Continue
ElseIf ascii = CHAR_DOT Then
GetWord.wType = WTYPE_HMS
Exit Function
ElseIf ascii = CHAR_COLON Then
GetWord.wType = WTYPE_HMS
Exit Function
Else
GetWord.wType = WTYPE_ERROR
Exit Function
End If
Case 2:
If pIndex > Len(pStr) Then
GetWord.wType = WTYPE_ERROR
Exit Function
ElseIf ascii >= CHAR_0 And ascii <= CHAR_9 Then
GetWord.wVal = GetWord.wVal + char
state = 3
GoTo Continue
Else
GetWord.wType = WTYPE_ERROR
Exit Function
End If
Case 3:
If pIndex > Len(pStr) Then
GetWord.wType = WTYPE_HMS
Exit Function
ElseIf ascii >= CHAR_0 And ascii <= CHAR_9 Then
GetWord.wVal = GetWord.wVal + char
GoTo Continue
ElseIf ascii = CHAR_DOT Then
GetWord.wType = WTYPE_HMS
Exit Function
ElseIf ascii = CHAR_COLON Then
GetWord.wType = WTYPE_HMS
Exit Function
Else
GetWord.wType = WTYPE_ERROR
Exit Function
End If
Case 4:
If pIndex > Len(pStr) Then
GetWord.wType = WTYPE_MS
Exit Function
ElseIf ascii >= CHAR_0 And ascii <= CHAR_9 Then
GetWord.wVal = GetWord.wVal + char
GoTo Continue
Else
GetWord.wType = WTYPE_ERROR
Exit Function
End If
End Select
Continue:
pIndex = pIndex + 1
Loop
End Function
|
|