From dcad1b86b147fadc01f2fbc70f7b3d8994ac3b78 Mon Sep 17 00:00:00 2001 From: xieguigang Date: Sat, 16 Jan 2021 23:04:26 +0800 Subject: [PATCH] enable sort key orders --- .../Expressions/Keywords/Options/OrderBy.vb | 3 +- LINQ/LINQ/Language/Tokenizer.vb | 3 +- LINQ/LINQ/Script/StackParser.vb | 5 ++- LINQ/LINQ/Script/SyntaxImplements.vb | 36 +++++++++++++++++-- LINQ/LINQ/test/Program.vb | 8 ++--- LINQ/test/query.linq | 2 +- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb index 620efe8..de590a9 100644 --- a/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb +++ b/LINQ/LINQ/Interpreter/Expressions/Keywords/Options/OrderBy.vb @@ -14,8 +14,9 @@ Namespace Interpreter.Expressions Dim key As Expression Dim desc As Boolean - Sub New(key As Expression) + Sub New(key As Expression, desc As Boolean) Me.key = FixLiteral(key) + Me.desc = desc End Sub Public Overrides Function Exec(context As ExecutableContext) As Object diff --git a/LINQ/LINQ/Language/Tokenizer.vb b/LINQ/LINQ/Language/Tokenizer.vb index be3be79..3241730 100644 --- a/LINQ/LINQ/Language/Tokenizer.vb +++ b/LINQ/LINQ/Language/Tokenizer.vb @@ -44,7 +44,8 @@ Namespace Language ReadOnly keywords As Index(Of String) = { "imports", "select", "from", "in", "let", "as", "distinct", "group", "by", "order", "aggregate", - "where", "take", "skip", "into" + "where", "take", "skip", "into", + "descending", "ascending" } ReadOnly operators As Index(Of String) = {"+", "-", "*", "/", "\", "%", "=", "<>", ">", "<", ">=", "<=", "^", "&"} ReadOnly literal As Index(Of String) = {"true", "false"} diff --git a/LINQ/LINQ/Script/StackParser.vb b/LINQ/LINQ/Script/StackParser.vb index f55be07..7c458bb 100644 --- a/LINQ/LINQ/Script/StackParser.vb +++ b/LINQ/LINQ/Script/StackParser.vb @@ -1,5 +1,6 @@ Imports System.Runtime.CompilerServices Imports LINQ.Language +Imports Microsoft.VisualBasic.ComponentModel.Collection Imports Microsoft.VisualBasic.Language Module StackParser @@ -36,9 +37,11 @@ Module StackParser Public Function SplitByTopLevelStack(tokenList As IEnumerable(Of Token)) As IEnumerable(Of Token()) + Static ignores As Index(Of String) = {"as", "by", "descending", "ascending"} + Return tokenList _ .DoSplitByTopLevelStack(Function(t) - Return t.name = Tokens.keyword AndAlso Not t.text.TextEquals("as") AndAlso Not t.text.TextEquals("by") + Return t.name = Tokens.keyword AndAlso (Not t.text.ToLower Like ignores) End Function, True, True, False) End Function diff --git a/LINQ/LINQ/Script/SyntaxImplements.vb b/LINQ/LINQ/Script/SyntaxImplements.vb index 69d775d..860f133 100644 --- a/LINQ/LINQ/Script/SyntaxImplements.vb +++ b/LINQ/LINQ/Script/SyntaxImplements.vb @@ -2,7 +2,9 @@ Imports LINQ.Interpreter.Expressions Imports LINQ.Interpreter.Query Imports LINQ.Language +Imports Microsoft.VisualBasic.ComponentModel.Collection Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel +Imports Microsoft.VisualBasic.Linq Namespace Script @@ -43,9 +45,29 @@ Namespace Script Return list End Function + ReadOnly sortOrders As Index(Of String) = {"descending", "ascending"} + - Public Function PopulateQueryExpression(tokens As IEnumerable(Of Token)) As Expression - Dim blocks = tokens.JoinOperators.SplitByTopLevelStack.ToArray + Public Function PopulateQueryExpression(tokenList As IEnumerable(Of Token)) As Expression + Dim blocks As List(Of Token()) = tokenList _ + .JoinOperators _ + .SplitByTopLevelStack _ + .ToList + + For i As Integer = 1 To blocks.Count - 1 + If i >= blocks.Count Then + Exit For + End If + + If blocks(i).Length = 1 AndAlso blocks(i)(Scan0).name = Tokens.keyword Then + If blocks(i)(Scan0).text.ToLower Like sortOrders Then + blocks(i - 1) = blocks(i - 1) _ + .JoinIterates(blocks(i)) _ + .ToArray + blocks.RemoveAt(i) + End If + End If + Next If blocks(Scan0).First.isKeywordFrom Then Return blocks(Scan0).CreateProjectionQuery(blocks.Skip(1).ToArray) @@ -160,7 +182,15 @@ Namespace Script ElseIf tokenList(Scan0).isKeyword("select") Then Return tokenList.Skip(1).GetProjection ElseIf tokenList(Scan0).isKeyword("order") Then - Return New OrderBy(ParseExpression(tokenList.Skip(2).ToArray)) + Dim sortKey = tokenList.Skip(2).ToArray + Dim desc As Boolean + + If sortKey.Last.name = Tokens.keyword AndAlso sortKey.Last.text.ToLower Like sortOrders Then + desc = sortKey.Last.text.TextEquals("descending") + sortKey = sortKey.Take(sortKey.Length - 1).ToArray + End If + + Return New OrderBy(ParseExpression(sortKey), desc) ElseIf tokenList(Scan0).isKeyword("take") Then Return New TakeItems(ParseExpression(tokenList.Skip(1).ToArray)) Else diff --git a/LINQ/LINQ/test/Program.vb b/LINQ/LINQ/test/Program.vb index f7d99aa..d1e6cf1 100644 --- a/LINQ/LINQ/test/Program.vb +++ b/LINQ/LINQ/test/Program.vb @@ -1,9 +1,9 @@ -Imports LINQ.Script +Imports LINQ.Interpreter +Imports LINQ.Interpreter.Query Imports LINQ.Runtime +Imports LINQ.Script Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel -Imports LINQ.Interpreter.Query Imports Microsoft.VisualBasic.My.JavaScript -Imports LINQ.Interpreter Public Module Program @@ -11,7 +11,7 @@ Public Module Program Dim test = From x As Double In {(1 + y) * 8, 2, 3, 4, 5, 6, 7, 8, 9} Where x ^ 3 > (5 * x) Select x = x ^ 2 + 99, y = x * 2 - Order By y + Order By y Ascending Sub Main() Call parserTest() diff --git a/LINQ/test/query.linq b/LINQ/test/query.linq index 054f084..199186d 100644 --- a/LINQ/test/query.linq +++ b/LINQ/test/query.linq @@ -9,5 +9,5 @@ SELECT x.LipidIon, x.Formula, x.PeakQuality, x."m-Score" -ORDER BY pow("m-Score", PeakQuality) +ORDER BY pow("m-Score", PeakQuality) DESCENDING TAKE 15 \ No newline at end of file