1 #Region "Microsoft.VisualBasic::abe9626741aeb1516607af3f6d1a4a8c, Microsoft.VisualBasic.Core\Scripting\TokenIcer\StackParser.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Module StackParser
35     
36     '         Function: __parsing, Parsing
37     
38     '         Sub: __printStack, PrintStack
39     
40     
41     ' /********************************************************************************/
42
43 #End Region
44
45 Imports System.Runtime.CompilerServices
46 Imports Microsoft.VisualBasic.Language
47
48 Namespace Scripting.TokenIcer
49
50     ''' <summary>
51     ''' Stack tree parser
52     ''' </summary>
53     Public Module StackParser
54
55         ''' <summary>
56         ''' 返回顶层的根节点
57         ''' </summary>
58         ''' <param name="source"></param>
59         ''' <param name="stackT">Pretend the root tokens as a true node</param>
60         ''' <returns></returns>
61         <Extension> Public Function Parsing(Of Tokens As IComparable)(source As IEnumerable(Of Token(Of Tokens)), stackT As StackTokens(Of Tokens)) As Func(Of Tokens)
62             Dim pretendDef As Token(Of Tokens) =
63                 New Token(Of Tokens)(stackT.Pretend, "Pretend")
64             Dim sourceQue As Queue(Of Token(Of Tokens)) =
65                 New Queue(Of Token(Of Tokens))(source)
66             Dim root As Func(Of Tokens) =
67                 New Func(Of Tokens) With {
68                 .Caller = New List(Of InnerToken(Of Tokens)) From {New InnerToken(Of Tokens)(pretendDef)},
69                 .Args = __parsing(source:=sourceQue, stackT:=stackT)
70             }
71             Return root
72         End Function
73
74         ''' <summary>
75         ''' 主要是解析当前的栈层之中的使用,逗号分隔的参数列表
76         ''' </summary>
77         ''' <param name="source"></param>
78         ''' <returns></returns>
79         Private Function __parsing(Of Tokens As IComparable)(source As Queue(Of Token(Of Tokens)), stackT As StackTokens(Of Tokens)) As Func(Of Tokens)()
80             Dim list As New List(Of Func(Of Tokens))
81             Dim current As Func(Of Tokens) = New Func(Of Tokens) With {
82                 .Caller = New List(Of InnerToken(Of Tokens))
83             }
84
85             Do While Not source.IsNullOrEmpty
86                 Dim x As Token(Of Tokens) = source.Dequeue
87
88                 If Not stackT.Equals(x.name, stackT.ParamDeli) Then
89                     ' 例如 test3( (3+-5.66)  +  6^4.5,7!)
90                     If stackT.Equals(x.name, stackT.LPair) Then ' 连续的两个左括号进行堆栈
91                         Dim stack As Func(Of Tokens)() = __parsing(source, stackT)
92                         Dim inner As New InnerToken(Of Tokens)(New Token(Of Tokens)(stackT.Pretend, "Pretend"), stack)
93                         Call current.Caller.Add(inner)
94                     Else
95                         Call current.Caller.Add(New InnerToken(Of Tokens)(x))
96                     End If
97                 End If
98
99                 If source.Count = 0 Then
100                     Call list.Add(current)
101                     Exit Do
102                 End If
103
104                 Dim peek As Token(Of Tokens) = source.Peek
105
106                 If stackT.Equals(peek.name, stackT.LPair) Then  ' 向下一层堆栈
107                     Call source.Dequeue()
108
109                     Dim currStack As New Func(Of Tokens)(current.Caller.Last)
110                     Call current.Caller.RemoveLast
111                     currStack.Args = __parsing(source, stackT)
112                     Call current.Caller.Add(New InnerToken(Of Tokens)(stackT.Pretend, currStack))
113                 ElseIf stackT.Equals(peek.name, stackT.RPair) Then  ' 向上一层退栈
114                     Call source.Dequeue()
115                     Call list.Add(current)
116                     Exit Do
117                 ElseIf stackT.Equals(x.name, stackT.ParamDeli) Then
118                     Call list.Add(current)
119
120                     current = New Func(Of Tokens) With {
121                         .Caller = New List(Of InnerToken(Of Tokens))
122                     }
123                 End If
124             Loop
125
126             If list.Count = 0 Then
127                 Call list.Add(current)
128             End If
129
130             Return list.ToArray
131         End Function
132
133         <Extension> Public Sub PrintStack(Of Tokens As IComparable)(x As Func(Of Tokens))
134             Call x.__DEBUG_ECHO
135             Call Console.WriteLine(New String("+", 120))
136             Call __printStack(x, Scan0)
137         End Sub
138
139         Private Sub __printStack(Of Tokens As IComparable)(obj As Func(Of Tokens), i As Integer)
140             Dim indent As String = New String(" ", i * 3)
141
142             For Each x As InnerToken(Of Tokens) In obj.Caller
143                 Call Console.WriteLine(indent & Scripting.ToString(x.obj))
144
145                 If Not x.InnerStack.IsNullOrEmpty Then
146                     For Each inner In x.InnerStack
147                         Call __printStack(inner, i + 1)
148                     Next
149                 End If
150             Next
151
152             If Not obj.Args.IsNullOrEmpty Then
153                 For Each x As Func(Of Tokens) In obj.Args
154                     Call __printStack(x, i + 1)
155                     Call Console.WriteLine(indent & "[Delimiter]")
156                 Next
157             End If
158         End Sub
159     End Module
160 End Namespace