一个简明的编译器

一个简明的编译器

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

写一个简单的编译器并不是很复杂的,当中要用到些反射的知识。自已觉得,反射的使用在 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

' 如

Published At
Categories with Web编程
Tagged with
comments powered by Disqus