欢迎光临
我们一直在努力

一个简明的编译器-.NET教程,面向对象编程

建站超值云服务器,限时71元/月

一个简明的编译器

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

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

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 一个简明的编译器-.NET教程,面向对象编程
分享到: 更多 (0)

相关推荐

  • 暂无文章