一个简明的编译器

原创 2004年11月03日 22:22:00

一个简明的编译器<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

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

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

 

一个简明的编译器{水如烟•村}

http://blog.csdn.net/lzmtw/archive/2004/11/03/166082.aspx
  • zzzjaychung
  • zzzjaychung
  • 2005年04月26日 19:45
  • 986

简明Python教程学习笔记_5_解决问题

问题 我提出的问题是: 我想要一个可以为我的所有重要文件创建备份的程序。 尽管这是一个简单的问题,但是问题本身并没有给我们足够的信息来解决它。进一步的分析是必需的。例如,我们如何确定该备份哪些文件?...
  • freeking101
  • freeking101
  • 2016年03月22日 22:14
  • 632

《简明python教程》的学习笔记

学习python的缘由 决心在一个这个寒假更加深入学习推荐系统之后,本来打算看数据挖掘导论或者是数据挖掘:概念与技术。不过在询问过一位学长之后,他推荐我看一看更加基础的书:集体智慧编程。该书所有的代...
  • xiaopihaierletian
  • xiaopihaierletian
  • 2017年05月24日 17:06
  • 1009

《简明Python教程》学习(一)

《简明Python教程》学习(一)一、 Python脚本开头为什么要写 #!/usr/bin/python1. 新建helloworld.py文件2. 内容print ‘hell...
  • cainiao_learn
  • cainiao_learn
  • 2016年11月16日 15:41
  • 1049

Python学习之《简明Python教程》(一)

以下内容为与Java语言的不同之处,需注意。1.注释 以“#”符号注释内容。2.四种数类型:整数、长整数、浮点数、复数3.字符串 (1) 可以使用单引号(’abc’)、双引号(”abc”)、三引号...
  • u012161134
  • u012161134
  • 2017年03月30日 18:43
  • 492

python简明教程-第十章解决问题-备份文件

需求: 输入需要备份的文件的目录,以及备份文件的存储路径,将备份文件压缩并以日期和时间存档 # --coding:utf-8-- import os import timesource = r'C:\...
  • u010274840
  • u010274840
  • 2016年06月28日 19:49
  • 256

简明Python教程笔记一 python3.x

《简明python教程》此教程用的是python 2.x与 python 3.x有些差异。 python有高效率的高层数据结构,面向对象。语法简洁,是门解释型脚本语言,适合应用程序的快速开发。 pyt...
  • Binbin_IT
  • Binbin_IT
  • 2017年10月24日 16:44
  • 187

备份脚本-学习《简明python教程》

#!/usr/bin/python #filename: backup_ver1.py # -*- coding: utf-8 -*- import os import time source = ...
  • zhouzhenhe2008
  • zhouzhenhe2008
  • 2015年12月28日 23:38
  • 400

慕课课程《简明世界史》课堂笔记二

课堂笔记二 一.基督教的产生 1.产生时间:公元1世纪20~30年代 2.基督的原意:救世主 3.对基督教做出重要贡献的人物:圣保罗 4.圣保罗的主要贡献是: (1)确定耶稣就是救世主; ...
  • u014028340
  • u014028340
  • 2015年05月27日 09:40
  • 509

git 简明指南---使用教程

Git基本概述 Git是一个分布式的版本控制系统,最初由Linus Torvalds编写,用作Linux内核代码的管理。在推出后,Git在其它项目中也取得了很大成功,尤其是在Ruby社区中。目前,包括...
  • ljheee
  • ljheee
  • 2016年05月25日 21:05
  • 590
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个简明的编译器
举报原因:
原因补充:

(最多只允许输入30个字)