A concise compiler Select BLOG from Lzmtw

xiaoxiao2021-03-06  94

A concise compiler

I have repeatedly seen the calculation problem of the text expression, and I will handle the previous code and add a comment.

Write a simple compiler is not very complicated, and you should use some reflection knowledge. Since it feels that the use of reflection is really ubiquitous in NET, and there is no efficiency of the use of reflection. After all, the current computer configuration is not very low. Appropriate use of reflections, or by using reflex itself, you will deepen your understanding of NET. In the future, you will write a small "article" for the use of reflection to increase the flexibility.

If only the value of the expression is calculated, there is of course so many code. This way to write, just make it versatile.

I put the code directly below, no longer say something (can say how to be stinky, just don't want to recruise).

Imports system.reflection

Imports system.codedom

Imports system.codedom.compiler

Public Class SourceComp

'// Compiler interface

Private m_compiler as icodecompiler

'// Compiler parameters

Private M_CompilerParameters as CompilerParameters

'// quoted assembly

Private m_refassemblies as string () = {"system.dll", "system.data.dll"}

'// source code

Private M_Source As String = ""

'// Record is the default source code

Private m_is_default as boolean = TRUE

'// Record the compilation status

PRIVATE M_Compiled as boolean = false

'// Compile the generated assembly

Private m_assembly as system.reflection.Assembly

'// The instance of the default source code generated

Private m_tmpclass as object

'// Default source code generated instance function

Private m_methodinfo as system.reflection.MethodInfo

'// Default source code function expression parameters

Private M_Expression As String

'// Return to the assembly

Public Readonly Property CPassembly () as system.reflection.Assembly

Get

Return me.m_assemblyMbly

END GET

End Property

Sub new ()

'// Get the VB compiler instance

Me.m_compiler = new vbcodeProvider (). CreateCompiler

'// initial compiler parameters

Me.m_compilerParameters = New CompilerParameters

With me.m_compilerparameters

.Generateexecutable = false '// false value specifies compiled as class set, True compiles to executable

.GenerateInMemory = false '// only generate an assembly in memory, not output to disk

'// Add a default assembly

Me.Add_compilerParameters ()

End with

End Sub

'// Add assembly to reference

Private sub add_compilerparameters ()

Me.m_compilerParameters.referenceDassemblies.addrange (me.m_refassemblies)

End Sub

'// Add a specified reference assembly

Public Sub Add_compilerParameters (BYVAL REFASSEMBLIES AS STRING ())

Me.m_refassemblies = Refassemblies

Me.m_compilerParameters.referenceDassemblies.clear () '// Clear the original assembly, repeat reference compilation will result in an exception

Me.Add_compilerParameters ()

End Sub

'// Generate a default source code

'// Category Name: TMPCLASS

'// Function Name: getExpressionValue, Parameters: Expression, Parameter Type: String

'// Main function: return the value of Expression Expression, return value type: Object

Private suildDefaultsource ()

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}") 'here incoming expressions

.Appendcode ("Return Result")

.Appendcode ("end function")

.Appendcode ("End Class")

End with

Me.m_source = mcodebuilder.tostring

End Sub

'// Specify source code

Public SUB STSource (Byval Source As String)

Me.m_source = SOURCE

Me.m_compiled = false

Me.m_is_default = false

End Sub

'// Read source code from the specified file

Public Sub getSourceFile (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

'// Compile

Public Sub Complile ()

If me.m_source = "" "

Me.builddefaultsource ()

END IF

If me.m_is_default then

'Incoming parameters

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)

'//Error message

IF (mcompResult.errors.haserror) THEN

Dim ErrorMessage As String

ErrorMessage = "Compile error:" & vbcrlf

Dim Err As CompileRrror

For Each Err in MCompResult.errors

ErrorMessage = ErrorMessage & Err.ErrorText & Vbcrlf

NEXT

Throw New Exception ("Compiling Error:" ErrorMessage)

END IF

Me.m_assembly = mcompResult.compiledassembly

ME.m_compiled = TRUE

End Sub

'// If it is the default source code, this function takes the value of the expression;

'// If you customize the source code, please refer to this function to write it yourself.

Public Function GetExpressionValue (Byval Expression As String) AS Object

IF not me.m_is_default the

Msgbox ("The code used is not the default code, this function is invalid")

Return Nothing

END IF

'If you have not compiled, compile

IF not me.m_compiled

'// Parameter expression as a code

Me.m_expression = expression

COMPLILE ()

'// Generate an instance, pay attention to the class name

Me.m_tmpclass = me.m_assembly.createInstance ("TMPCLASS")

'// Take a function, pay attention to the case

m_methodInfo = me.m_tmpclass.gettype (). getMethod ("getExpressionValue")

END IF

'//Calculation results

Dim Result As Object = m_methodinfo.invoke (m_tmpclass, nothing)

'The expression is different when it is different.

Me.m_compiled = false

Return RESULT

END FUNCTION

END CLASS

'// format the class to generate or read the code

Public Class CodeBuilder

Private _stringbuilder as system.text.stringbuilder

'// format, {0} is the number of spaces, {1} code strings, finally add to the train

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

'// Directly read code from existing VB files

Public Sub appendfromfile (Byval FileName As String)

IF not system.io.file.exists (filename) THEN

MsgBox (FileName & "does not exist.")

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, oosed)

Dim Reader As New System.io.StreamReader (fs, system.text.encoding.default)

TMPSTR = Reader.ReadToend

Reader.close ()

fs.close ()

_StringBuilder.Append (tmpstr)

End Sub

'// Return to the code string

Public overrides function toString () AS STRING

Return_stringbuilder.tostring

END FUNCTION

'// Clear the original code

Public Sub Clear ()

IF_StringBuilder.Length> 0 Then _stringbuilder.remove (0, _StringBuilder.Length - 1)

End Sub

End Class' CodeBuilder

'test

DIM MyComp as SourceComp

Private sub button1_click (byvale as system.object, byval e as system.eventargs) Handles Button1.click

'If you don't regenerate an instance, you will be wrong due to the temporary assembly of the same name when recompilated.

Mycomp = new sourceComp

Console.writeline (MyComp.GetexpressionValue ("Math.Round (Math.SQRT (123 * 456), 2)") .tostring)

'Result 236.83

Mycomp = new sourceComp

Console.writeline (MyComp.GetexpressionValue ("123 * 456> 12 * 6987"). TOSTRING)

'Result False

End Sub

转载请注明原文地址:https://www.9cbs.com/read-96269.html

New Post(0)