migrants the c# parser

master
謝桂綱 10 years ago
parent a9e0b7592f
commit aed54ba458

@ -55,8 +55,22 @@ Namespace LDM.Expression
Protected Overrides Function __parsing() As CodeExpression
Dim expr As Func(Of Tokens) =
MyBase._source.Source.ParsingStack.Args.First '
Dim code As New CodeExpression
For Each c In expr.Caller
If c.InnerStack Is Nothing Then
If c.obj.TokenName = Tokens.varRef Then
End If
Else
End If
Next
Return code
End Function
Public Const ARGV As String = "obj"
Public Const TestMethod As String = "___test"
Private Function __buildFunc() As CodeMemberMethod

@ -0,0 +1,259 @@
Imports System.CodeDom
Imports System.Collections.Generic
Imports System.Collections.Specialized
Imports Microsoft.VisualBasic.Linq.Statements.TokenIcer
Imports Microsoft.VisualBasic.Scripting.TokenIcer
Namespace LDM.Parser
''' <summary>
''' Parses expressions written in strings into CodeDom expressions. There is a certain
''' amount of context that the parser may need to be familiar with. This is why the
''' parsing methods are not exposed as static.
''' </summary>
Public Class Parser : Implements System.IDisposable
Private _Enums As Dictionary(Of String, CodeTypeReference) = New Dictionary(Of String, CodeTypeReference)
Private _Fields As StringCollection = New StringCollection
''' <summary>
''' A collection of identifiers that should be recognized as enums.
''' </summary>
Public ReadOnly Property Enums() As Dictionary(Of String, CodeTypeReference)
Get
Return _Enums
End Get
End Property
''' <summary>
''' A collection of names of fields.
''' </summary>
Public ReadOnly Property Fields() As StringCollection
Get
Return _Fields
End Get
End Property
''' <summary>
''' Parses an expression into a <see cref="CodeExpression"/>.
''' </summary>
''' <param name="exp">expression to parse</param>
''' <returns>CodeDom representing the expression</returns>
Public Function ParseExpression(exp As Token(Of Tokens)()) As CodeExpression
Return ReadExpression(exp, Scan0, TokenPriority.None)
End Function
''' <summary>
''' Recursive method that reads an expression.
''' </summary>
''' <param name="t"></param>
''' <param name="priority"></param>
''' <returns></returns>
Private Function ReadExpression(t As Token(Of Tokens)(), [next] As Integer, priority As TokenPriority) As CodeExpression
Dim left As CodeExpression = Nothing, right As CodeExpression = Nothing
Dim cont As Boolean = True, applyNot As Boolean = False, applyNegative As Boolean = False
While cont
Dim current As Token(Of Tokens) = t([next].MoveNext)
Select Case current.TokenName
Case Tokens.Float OrElse Tokens.Integer OrElse Tokens.String
left = New CodePrimitiveExpression(current.TryCast)
t.GetNextToken()
cont = False
Case TokenType.[Operator]
' An operator here is considered a unary operator.
Select Case t.Current.Text
Case "-"
applyNegative = True
Case "!"
applyNot = True
Case Else
Throw New Exception("Unexpected operator: " & t.Current.Text)
End Select
t.GetNextToken()
Continue While
Case TokenType.Identifier
left = ReadIdentifier(t)
cont = False
Case TokenType.OpenParens
t.GetNextToken()
left = ReadExpression(t, TokenPriority.None)
t.GetNextToken()
If TypeOf left Is CodeTypeReferenceExpression Then
left = New CodeCastExpression(TryCast(left, CodeTypeReferenceExpression).Type, ReadExpression(t, TokenPriority.None))
End If
cont = False
End Select
If t.IsInvalid Then
cont = False
End If
End While
If left Is Nothing Then
Throw New Exception("No expression found.")
End If
If applyNot Then
left = New CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.ValueEquality, New CodePrimitiveExpression(False))
ElseIf applyNegative Then
left = New CodeBinaryOperatorExpression(New CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, left)
End If
If t.IsInvalid OrElse t.Current.Type = TokenType.CloseParens OrElse t.Current.Type = TokenType.Comma OrElse t.Current.Type = TokenType.CloseBracket Then
Return left
End If
cont = True
While cont AndAlso Not t.IsInvalid
Dim token As Token = t.Current
Select Case token.Type
Case TokenType.[Operator]
If t.Current.Priority < priority Then
cont = False
Else
' In the case we have an operator, we'll assume it's a binary operator.
Dim binOp As CodeBinaryOperatorType
Dim notEquals As Boolean = False
Select Case token.Text
Case ">"
binOp = CodeBinaryOperatorType.GreaterThan
Case ">="
binOp = CodeBinaryOperatorType.GreaterThanOrEqual
Case "<"
binOp = CodeBinaryOperatorType.LessThan
Case "<="
binOp = CodeBinaryOperatorType.LessThanOrEqual
Case "=", "=="
binOp = CodeBinaryOperatorType.ValueEquality
Case "!="
binOp = CodeBinaryOperatorType.ValueEquality
notEquals = True
Case "|"
binOp = CodeBinaryOperatorType.BitwiseOr
Case "||"
binOp = CodeBinaryOperatorType.BooleanOr
Case "&"
binOp = CodeBinaryOperatorType.BitwiseAnd
Case "&&"
binOp = CodeBinaryOperatorType.BooleanAnd
Case "-"
binOp = CodeBinaryOperatorType.Subtract
Case "+"
binOp = CodeBinaryOperatorType.Add
Case "/"
binOp = CodeBinaryOperatorType.Divide
Case "%"
binOp = CodeBinaryOperatorType.Modulus
Case "*"
binOp = CodeBinaryOperatorType.Multiply
Case Else
Throw New Exception("Unrecognized operator: " & t.Current.Text)
End Select
If t.IsInvalid Then
Throw New Exception("Expected token for right side of binary expression.")
End If
t.GetNextToken()
right = ReadExpression(t, token.Priority)
left = New CodeBinaryOperatorExpression(left, binOp, right)
' If the operator was the not equals operator, we just negate the previous binary expression.
If notEquals Then
left = New CodeBinaryOperatorExpression(left, binOp, New CodePrimitiveExpression(False))
End If
End If
Case TokenType.CloseParens
't.GetNextToken();
cont = False
Case TokenType.Dot
' A dot could appear after some parentheses. In this case we need to parse
' what's after the dot as an identifier.
t.GetNextToken()
right = ReadIdentifier(t)
Dim ceTemp As CodeExpression = right
While True
If TypeOf ceTemp Is CodeVariableReferenceExpression Then
left = New CodePropertyReferenceExpression(left, TryCast(ceTemp, CodeVariableReferenceExpression).VariableName)
Exit While
ElseIf TypeOf ceTemp Is CodePropertyReferenceExpression Then
Dim cpre As CodePropertyReferenceExpression = TryCast(ceTemp, CodePropertyReferenceExpression)
If TypeOf cpre.TargetObject Is CodeThisReferenceExpression Then
cpre.TargetObject = left
left = cpre
Exit While
Else
ceTemp = cpre.TargetObject
End If
ElseIf TypeOf ceTemp Is CodeFieldReferenceExpression Then
Dim cfre As CodeFieldReferenceExpression = TryCast(ceTemp, CodeFieldReferenceExpression)
If TypeOf cfre.TargetObject Is CodeThisReferenceExpression Then
cfre.TargetObject = left
left = cfre
Exit While
End If
ElseIf TypeOf ceTemp Is CodeMethodInvokeExpression Then
Dim cmie As CodeMethodInvokeExpression = TryCast(ceTemp, CodeMethodInvokeExpression)
If TypeOf cmie.Method.TargetObject Is CodeThisReferenceExpression Then
cmie.Method.TargetObject = left
left = cmie
Exit While
Else
ceTemp = cmie.Method.TargetObject
End If
Else
Throw New Exception("Unexpected identifier found after .")
End If
End While
cont = False
Case Else
Throw New Exception("Token not expected: " & token.Text)
End Select
End While
Return left
End Function
''' <summary>
''' When an identifier is encountered, it could be a number of things. A single identifer by itself
''' is considered a variable. The pattern identifier[.identifier]+ will consider the
''' first identifier as a variable and the others as properties. Any identifier that is followed
''' by an open parenthesis is considered to be a function call. Indexes are not handled yet, but
''' should be handled in the future. If the identifier is "this" then a this reference is used.
''' </summary>
''' <param name="t"></param>
''' <returns></returns>
Private Function ReadIdentifier(t As Tokenizer) As CodeExpression
Dim ce As CodeExpression = Nothing
Dim token As Token = t.Current
ce = New CodeVariableReferenceExpression(token.Text)
token = t.GetNextToken()
Return ce
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean '
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: ()
End If
' TODO: () Finalize()
' TODO: null
End If
Me.disposedValue = True
End Sub
' TODO: Dispose(ByVal disposing As Boolean) Finalize()
'Protected Overrides Sub Finalize()
' ' Dispose(ByVal disposing As Boolean)
' Dispose(False)
' MyBase.Finalize()
'End Sub
' Visual Basic
Public Sub Dispose() Implements IDisposable.Dispose
' Dispose (disposing As Boolean)
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace

@ -0,0 +1,52 @@
Namespace LDM.Parser
''' <summary>
''' Indicates priority in order of operations.
''' </summary>
Public Enum TokenPriority
''' <summary>
''' Default
''' </summary>
None
''' <summary>
''' Bitwise or
''' </summary>
[Or]
''' <summary>
''' Bitwise and
''' </summary>
[And]
''' <summary>
''' Bitwise not
''' </summary>
[Not]
''' <summary>
''' Equality comparisons like &gt;, &lt;=, ==, etc.
''' </summary>
Equality
''' <summary>
''' Plus or minus
''' </summary>
PlusMinus
''' <summary>
''' Modulus
''' </summary>
[Mod]
''' <summary>
''' Multiply or divide
''' </summary>
MulDiv
''' <summary>
''' Unary minus
''' </summary>
UnaryMinus
End Enum
End Namespace

@ -126,8 +126,10 @@
<Compile Include="LDM\Expression\LetClosure.vb" />
<Compile Include="LDM\Expression\SelectClosure.vb" />
<Compile Include="LDM\Expression\WhereClosure.vb" />
<Compile Include="LDM\Parser\TokenPriority.vb" />
<Compile Include="LDM\Parser\ClosureTokens.vb" />
<Compile Include="LDM\Parser\ClosureParser.vb" />
<Compile Include="LDM\Parser\Parser.vb" />
<Compile Include="LDM\TokenIcer.vb" />
<Compile Include="Framewok\SDK_PATH.vb" />
<Compile Include="Framewok\ObjectModel\ParallelLINQ.vb" />

Loading…
Cancel
Save