一个简明的编译器

发布时间: 2007-05-21 09:40    作者: 未知    来源: 未知    浏览:    评论

一个简明的编译器



多次看到有人提起文本表达式的计算问题,就动手整理以前的代码并加上注释。

写一个简单的编译器并不是很复杂的,当中要用到些反射的知识。自已觉得,反射的使用在NET中真是无处不在,使用反射没什么效率不效率的问题,毕竟现在的电脑配置并不是很低。适当使用反射,或者通过使用反射本身,会使自己加深对NET的理解。以后会写些运用反射增加代码灵活性的小”文章”供初学者参考。


如果只是计算表达式的值的,当然用不了那么多的代码.这样写法,只是使它通用性强些.


以下的我直接贴代码了,不再说些什么(可以说如何如何臭,只是不许骂人)。



Imports System.Reflection

Imports System.CodeDom

Imports System.CodeDom.Compiler

Public Class SourceComp



'//编译器接口

Private m_Compiler As ICodeCompiler

'//编译器参数

Private m_CompilerParameters As CompilerParameters

'//引用的程序集

Private m_RefAssemblies As String() = {"System.dll", "System.Data.dll"}

'//源代码

Private m_Source As String = ""

'//记录是否是默认的源代码

Private m_Is_Default As Boolean = True

'//记录编译状态

Private m_Compiled As Boolean = False

'//编译生成的程序集

Private m_Assembly As System.Reflection.Assembly

'//默认源代码生成的实例

Private m_tmpClass As Object

'//默认源代码生成的实例函数

Private m_MethodInfo As System.Reflection.MethodInfo

'//默认源代码函数的表达式参数

Private m_Expression As String

'//返回程序集

Public ReadOnly Property cpAssembly() As System.Reflection.Assembly

Get

Return Me.m_Assembly

End Get

End Property

Sub New()

'//获取VB编译器实例

Me.m_Compiler = New VBCodeProvider().CreateCompiler

'//初始编译器参数

Me.m_CompilerParameters = New CompilerParameters

With Me.m_CompilerParameters

.GenerateExecutable = False '//False值指定编译为类集,True编译为可执行程序

.GenerateInMemory = False '//只在内存中生成程序集,不输出到磁盘

'//添加默认的程序集

Me.Add_CompilerParameters()

End With

End Sub



'//添加要引用的程序集

Private Sub Add_CompilerParameters()

Me.m_CompilerParameters.ReferencedAssemblies.AddRange(Me.m_RefAssemblies)

End Sub

'//添加指定的引用程序集

Public Sub Add_CompilerParameters(ByVal RefAssemblies As String())

Me.m_RefAssemblies = RefAssemblies

Me.m_CompilerParameters.ReferencedAssemblies.Clear() '//清除原有的程序集,重复引用编译会产生异常

Me.Add_CompilerParameters()

End Sub



'//生成默认的源代码

'//类名:tmpClass

'//函数名:GetExpressionValue ,参数:Expression ,参数类型:字符串

'//主要功能:返回表达式Expression的值 ,返回值类型:Object

Private Sub BuildDefaultSource()

Dim mCodeBuilder As CodeBuilder = New CodeBuilder

With mCodeBuilder

.AppendCode("Imports System")

.AppendCode("Imports System.Data")

.AppendCode("Imports System.Math")

.AppendCode("Imports Microsoft.VisualBasic")

.AppendCode()

.AppendCode("Public Class tmpClass")

.AppendCode(" Public Function GetExpressionValue() As Object")

.AppendCode(" Dim Result As Object")

.AppendCode(" Result={0}") '这里传入表达式

.AppendCode(" Return Result")

.AppendCode(" End Function")

.AppendCode("End Class")

End With

Me.m_Source = mCodeBuilder.ToString

End Sub

'//指定源代码

Public Sub SetSource(ByVal Source As String)

Me.m_Source = Source

Me.m_Compiled = False

Me.m_Is_Default = False

End Sub

'//从指定文件中读取源代码

Public Sub GetSourceFormFile(ByVal SourceFileName As String)

Dim mCodeBuilder As CodeBuilder = New CodeBuilder

mCodeBuilder.AppendFromFile(SourceFileName)

Me.m_Source = mCodeBuilder.ToString

Me.m_Compiled = False

Me.m_Is_Default = False

End Sub





'//编译

Public Sub Complile()

If Me.m_Source = "" Then

Me.BuildDefaultSource()

End If

If Me.m_Is_Default Then

'传入参数

Me.m_Source = String.Format(Me.m_Source, Me.m_Expression)

End If



Dim mCompResult As CompilerResults = Me.m_Compiler.CompileAssemblyFromSource(Me.m_CompilerParameters, Me.m_Source)

'//错误提示

If (mCompResult.Errors.HasErrors) Then

Dim ErrorMessage As String

ErrorMessage = "编译错误:" & vbCrLf

Dim Err As CompilerError

For Each Err In mCompResult.Errors

ErrorMessage = ErrorMessage & Err.ErrorText & vbCrLf

Next

Throw New Exception("编译错误: " + ErrorMessage)

End If

Me.m_Assembly = mCompResult.CompiledAssembly

Me.m_Compiled = True

End Sub





'//如果是默认源代码,此函数取表达式的值;

'//如果自定义源代码,请参考本函数视实际自己写

Public Function GetExpressionValue(ByVal Expression As String) As Object

If Not Me.m_Is_Default Then

MsgBox("所用的代码不是默认代码,此函数无效")

Return Nothing

End If



'如果还没有编译则编译

If Not Me.m_Compiled Then
'//传入参数表达式作为代码


Me.m_Expression = Expression

Complile()

'//生成实例,注意类名区分大小写

Me.m_tmpClass = Me.m_Assembly.CreateInstance("tmpClass")

'//取函数,注意大小写

m_MethodInfo = Me.m_tmpClass.GetType().GetMethod("GetExpressionValue")

End If

'//计算结果

Dim Result As Object = m_MethodInfo.Invoke(m_tmpClass, Nothing)


'表达式不同时要重新编译
Me.m_Compiled = False

Return Result

End Function



End Class





'//格式生成或读取代码的类

Public Class CodeBuilder

Private _StringBuilder As System.Text.StringBuilder

'//格式,{0}为空格数,{1}代码字串,最后加回车换行

Private Const CodeFormat As String = "{0}{1}" & ControlChars.CrLf

Sub New()

_StringBuilder = New System.Text.StringBuilder

End Sub

Public Overloads Sub AppendCode()

_StringBuilder.AppendFormat(CodeFormat, Space(0), Space(0))

End Sub

Public Overloads Sub AppendCode(ByVal CodeString As String)

_StringBuilder.AppendFormat(CodeFormat, Space(0), CodeString)

End Sub

Public Overloads Sub AppendCode(ByVal CodeFloor As Integer, ByVal CodeString As String)

_StringBuilder.AppendFormat(CodeFormat, Space(CodeFloor * 4), CodeString)

End Sub

'//直接从已有vb文件中读取代码

Public Sub AppendFromFile(ByVal FileName As String)

If Not System.IO.File.Exists(FileName) Then

MsgBox(FileName & "不存在.")

Exit Sub

End If

Dim tmpStr As String

Dim fs As System.IO.FileStream

fs = New System.IO.FileStream(FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)

Dim Reader As New System.IO.StreamReader(fs, System.Text.Encoding.Default)

tmpStr = Reader.ReadToEnd

Reader.Close()

fs.Close()

_StringBuilder.Append(tmpStr)

End Sub

'//返回代码串

Public Overrides Function ToString() As String

Return _StringBuilder.ToString

End Function

'//清除原有代码

Public Sub Clear()

If _StringBuilder.Length > 0 Then _StringBuilder.Remove(0, _StringBuilder.Length - 1)

End Sub

End Class 'CodeBuilder





'测试

Dim MyComp As SourceComp

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'如果不重新生成实例,则因重新编译时输出同名的临时程序集,会出错

MyComp = New SourceComp

Console.WriteLine(MyComp.GetExpressionValue("Math.Round(Math.SQRT(123 * 456), 2) ").ToString)

'结果236.83

MyComp = New SourceComp

Console.WriteLine(MyComp.GetExpressionValue("123 * 456 > 12 * 6987").ToString)

'结果False

End Sub



TAG

Smile Big Smile Surprise Stick out tongue Wink Sad Tongue Tied Indifferent Crying Embarrassed Cool Angry Angel Devil [8-|] [:#] [:-*] [:^)] [<:o)] [|-)] Yes Beer Left Hug Music Star Time Snail Pizza Automobile Umbrella Computer Storm [mo] [8o|] [^o)] [+o(] [*-)] [8-)] Coffee No Drinks [Z] Right Hug Cake Broken Heart Gift Wilted Flower Movie Dog Idea Sleep Email Travel Paradise
呢称:

加粗 斜体 下划线 链接 图片 代码 邮件地址 引用 列表

最多只能输入100个字符

Tags

SQL 数据库 asp.net C# XML 控件 .NET教程 程序 事件 数据 安全 代码 Server 客户端 验证 数据库专栏 接口 文件 Oracle DataSet 函数 DataGrid 问题 .net return C#语言 JavaScript 服务 IIS 对象 语句 windows 继承 时间 web.config 设计 开发 参数 变量 解决 字符 ADO.net 环境 VB.Net语言 web 异常 工具 服务器 计算 实例 OLEDB Application VB Word WebService insert asp net 安装 记录

精华推荐

更多

精品下载

更多