明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 11202|回复: 15

[VBA]公式解析源代码,仅包含四则运算部分。

  [复制链接]
发表于 2003-11-20 21:23:00 | 显示全部楼层 |阅读模式
花了两天时间,终于将一个C#编写的公式解析程序转化为VB的代码,不过还有很多东西没有实现,比如函数和变量功能的实现,有兴趣的可以自己研究,也可以参考编译原理这本书。

  1. Enum tokTypes
  2.     tokNONE = 0
  3.     tokDELIMITER = 1
  4.     tokVARIABLE = 2
  5.     tokFUNCTION = 3
  6.     tokNumber = 4
  7.     tokString = 5
  8. End Enum
  9. Dim exp As String
  10. Dim expIdx As Integer
  11. Dim token As String
  12. Dim tokType As tokTypes

  13. ' 判断是否指定的分隔符
  14. Function IsDelim(ByVal c As String) As Boolean
  15.     If InStr("+-*/&()", c) Then IsDelim = True
  16. End Function

  17. ' 判断是否是字母
  18. Function IsLetter(ByVal c As String) As Boolean
  19.     If Asc(c) >= 65 And Asc(c) <= 90 Then
  20.         IsLetter = True
  21.     ElseIf Asc(c) >= 97 And Asc(c) <= 122 Then
  22.         IsLetter = True
  23.     End If
  24. End Function

  25. '判断是否是数字
  26. Function IsDigit(ByVal c As String) As Boolean
  27.     If Asc(c) >= 48 And Asc(c) <= 57 Then IsDigit = True
  28. End Function

  29. '判断是否是空格
  30. Function IsWhiteSpace(ByVal c As String) As Boolean
  31.     If c = " " Then IsWhiteSpace = True
  32. End Function

  33. '取计算单元标记
  34. Sub GetToken()
  35.     tokType = tokNONE
  36.     token = ""
  37.     If expIdx > Len(exp) Then Exit Sub
  38.     '忽略前置空格
  39.     Do While (expIdx <= Len(exp) And IsWhiteSpace(Mid(exp, expIdx, 1)))
  40.         expIdx = expIdx + 1
  41.         If expIdx > Len(exp) Then Exit Sub
  42.     Loop
  43.     '分隔符
  44.     If (IsDelim(Mid(exp, expIdx, 1))) Then
  45.         token = token + Mid(exp, expIdx, 1)
  46.         expIdx = expIdx + 1
  47.         tokType = tokDELIMITER
  48.     '函数或者变量
  49.     ElseIf (IsLetter(Mid(exp, expIdx, 1))) Then
  50.        token = token + Mid(exp, expIdx, 1)
  51.         expIdx = expIdx + 1
  52.         If expIdx > Len(exp) Then Exit Sub
  53.         Do While (IsLetter(Mid(exp, expIdx, 1)) And IsDigit(Mid(exp, expIdx, 1)))
  54.             token = token + Mid(exp, expIdx, 1)
  55.             expIdx = expIdx + 1
  56.             If expIdx > Len(exp) Then Exit Do
  57.         Loop
  58.         tokType = tokFUNCTION
  59.     '数字
  60.     ElseIf (IsDigit(Mid(exp, expIdx, 1))) Then
  61.         Do While Not (IsDelim(Mid(exp, expIdx, 1)))
  62.             token = token + Mid(exp, expIdx, 1)
  63.             expIdx = expIdx + 1
  64.             If expIdx > Len(exp) Then Exit Do
  65.         Loop
  66.         tokType = tokNumber
  67.     '字符串
  68.     ElseIf (Mid(exp, expIdx, 1) = """") Then
  69.         expIdx = expIdx + 1
  70.         Do While (Mid(exp, expIdx, 1) <> """")
  71.             token = token + Mid(exp, expIdx, 1)
  72.             expIdx = expIdx + 1
  73.             If expIdx > Len(exp) Then Exit Do
  74.         Loop
  75.         expIdx = expIdx + 1
  76.         tokType = tokString
  77.     End If
  78. End Sub

  79. Function Evaluate(ByVal expstr As String)
  80.     exp = expstr
  81.     expIdx = 1
  82.     GetToken
  83.     If (tokType = tokNONE And token = """") Then MsgBox ("No Expression Present!")
  84.     Evaluate = EvalExp2()
  85.     MsgBox Evaluate
  86. End Function

  87. '处理加法或减法
  88. Function EvalExp2() As String
  89.     Dim result As String
  90.     Dim op As String
  91.     Dim partialResult As String
  92.     EvalExp2 = EvalExp3()
  93.     op = token
  94.     Do While (op = "+" Or op = "-" Or op = "&")
  95.         GetToken
  96.         partialResult = EvalExp3()
  97.         Select Case op
  98.             Case "-":
  99.                 EvalExp2 = CDbl(EvalExp2) - CDbl(partialResult)
  100.             Case "+":
  101.                 EvalExp2 = CDbl(EvalExp2) + CDbl(partialResult)
  102.             Case "&":
  103.                 EvalExp2 = EvalExp2 + partialResult
  104.         End Select
  105.         op = token
  106.     Loop
  107. End Function

  108. '处理乘法或除法
  109. Function EvalExp3() As String
  110.     Dim op As String
  111.     Dim partialResult  As String
  112.     EvalExp3 = EvalExp5
  113.     op = token
  114.     Do While (op = "*" Or op = "/")
  115.         GetToken
  116.         partialResult = EvalExp5
  117.         Select Case op
  118.             Case "*":
  119.                 EvalExp3 = CDbl(EvalExp3) * CDbl(partialResult)
  120.             Case "/":
  121.                 EvalExp3 = CDbl(EvalExp3) / CDbl(partialResult)
  122.         End Select
  123.         op = token
  124.     Loop
  125. End Function

  126. '处理一元
  127. Function EvalExp5() As String
  128.     Dim op As String
  129.     Dim partialResult  As String
  130.     op = ""
  131.     If ((tokType = tokDELIMITER) And (token = "+" Or token = "-")) Then
  132.         op = token
  133.         GetToken
  134.     End If
  135.     EvalExp5 = EvalExp6
  136.     If (op = "-") Then EvalExp5 = -1 * EvalExp5
  137. End Function

  138. '处理括号
  139. Function EvalExp6() As String
  140.     If ((token = "(")) Then
  141.         GetToken
  142.         EvalExp6 = EvalExp2()
  143.         GetToken
  144.     Else
  145.         EvalExp6 = Atom()
  146.     End If
  147. End Function

  148. '处理数字或字符串
  149. Function Atom() As String
  150.     Select Case tokType
  151.         Case tokNumber:
  152.             Atom = token
  153.             GetToken
  154.         Case tokString:
  155.             Atom = token
  156.             GetToken
  157.     End Select
  158. End Function

  159. Sub main()
  160.     Evaluate "3+5*(2.5+7.5)-8/2"
  161. End Sub
 楼主| 发表于 2003-11-20 21:30:00 | 显示全部楼层
附上它的代码分析程序,是C#格式,可以参考。
没接触过C#的编程,可能转化的过程当中有些不是处理的很好,另外错误分析的部分也没处理。
附件是用WinRAR3.20版本压缩的,如果打不开,请下载新的版本。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2004-1-19 22:28:00 | 显示全部楼层
好东西啊~~送花一朵!
发表于 2004-2-6 21:14:00 | 显示全部楼层

好程序呀

好程序呀!
发表于 2006-4-21 00:34:00 | 显示全部楼层
确实很好啊.谢谢啊.
发表于 2008-10-17 17:38:00 | 显示全部楼层
不错
发表于 2009-4-2 09:25:00 | 显示全部楼层
谢谢
发表于 2009-10-10 12:09:00 | 显示全部楼层

好东西大家分享

发表于 2009-10-15 18:53:00 | 显示全部楼层

为啥看不到呢?

\

发表于 2009-11-8 16:59:00 | 显示全部楼层

在哪里啊

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 12:29 , Processed in 0.175872 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表