-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathWitSql.cs
More file actions
96 lines (81 loc) · 3.27 KB
/
Copy pathWitSql.cs
File metadata and controls
96 lines (81 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using Antlr4.Runtime;
using OutWit.Database.Parser.Exceptions;
using OutWit.Database.Parser.Expressions;
using OutWit.Database.Parser.Generated;
using OutWit.Database.Parser.Statements;
using OutWit.Database.Parser.Visitor;
namespace OutWit.Database.Parser;
/// <summary>
/// Entry point for parsing WitSQL statements.
/// </summary>
public static class WitSql
{
/// <summary>
/// Tries to parse SQL text. Returns result with errors if parsing fails.
/// </summary>
public static WitSqlParsingResult TryParse(string sql)
{
ArgumentNullException.ThrowIfNull(sql);
var inputStream = new AntlrInputStream(sql);
var lexer = new WitSqlLexer(inputStream);
var tokenStream = new CommonTokenStream(lexer);
var parser = new WitSqlParser(tokenStream);
var errorListener = new WitSqlParsingErrorListener();
lexer.RemoveErrorListeners();
lexer.AddErrorListener(errorListener);
parser.RemoveErrorListeners();
parser.AddErrorListener(errorListener);
var context = parser.script();
if (errorListener.Errors.Count > 0)
return new WitSqlParsingResult { Errors = errorListener.Errors };
var visitor = new WitSqlVisitor();
var statements = visitor.VisitScript(context);
return new WitSqlParsingResult { Statements = statements };
}
/// <summary>
/// Parses SQL text into AST. Throws WitSqlParsingException on error.
/// </summary>
/// <param name="sql">SQL text to parse</param>
/// <returns>List of parsed statements</returns>
/// <exception cref="WitSqlParsingException">When parsing fails</exception>
public static IReadOnlyList<WitSqlStatement> Parse(string sql)
{
var result = TryParse(sql);
return result.IsSuccess
? result.Statements
: throw new WitSqlParsingException(result.Errors);
}
/// <summary>
/// Parses a single SQL statement. Throws if there are multiple statements.
/// </summary>
public static WitSqlStatement ParseStatement(string sql)
{
var statements = Parse(sql);
if (statements.Count == 0)
{
throw new WitSqlParsingException([new WitSqlParsingError { Line = 1, Column = 0, Message = "No statement found" }]);
}
if (statements.Count > 1)
{
throw new WitSqlParsingException([new WitSqlParsingError { Line = 1, Column = 0, Message = $"Expected single statement, got {statements.Count}" }]);
}
return statements[0];
}
/// <summary>
/// Parses a SQL expression.
/// </summary>
public static WitSqlExpression ParseExpression(string expr)
{
// Wrap in SELECT to parse as expression
var statements = Parse($"SELECT {expr}");
if (statements.Count != 1 || statements[0] is not WitSqlStatementSelect select)
{
throw new WitSqlParsingException([new WitSqlParsingError { Line = 1, Column = 0, Message = "Failed to parse expression" }]);
}
if (select.SelectList.Count != 1 || select.SelectList[0].Expression == null)
{
throw new WitSqlParsingException([new WitSqlParsingError { Line = 1, Column = 0, Message = "Invalid expression" }]);
}
return select.SelectList[0].Expression;
}
}