Skip to content

Commit fec4808

Browse files
committed
Refactor parseExpr to allow to use the priority precedence
1 parent c1f72b5 commit fec4808

File tree

45 files changed

+866
-356
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+866
-356
lines changed

parser/ast.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,7 +1475,8 @@ type CreateTable struct {
14751475
OnCluster *ClusterClause
14761476
TableSchema *TableSchemaClause
14771477
Engine *EngineExpr
1478-
SubQuery *SubQueryClause
1478+
Alias *AliasExpr
1479+
SubQuery *SubQuery
14791480
HasTemporary bool
14801481
}
14811482

@@ -1518,6 +1519,7 @@ func (c *CreateTable) String() string {
15181519
builder.WriteString(c.Engine.String())
15191520
}
15201521
if c.SubQuery != nil {
1522+
builder.WriteString(" AS ")
15211523
builder.WriteString(c.SubQuery.String())
15221524
}
15231525
return builder.String()
@@ -1562,7 +1564,7 @@ type CreateMaterializedView struct {
15621564
OnCluster *ClusterClause
15631565
Engine *EngineExpr
15641566
Destination *DestinationClause
1565-
SubQuery *SubQueryClause
1567+
SubQuery *SubQuery
15661568
Populate bool
15671569
}
15681570

@@ -1604,6 +1606,7 @@ func (c *CreateMaterializedView) String() string {
16041606
builder.WriteString(" POPULATE ")
16051607
}
16061608
if c.SubQuery != nil {
1609+
builder.WriteString(" AS ")
16071610
builder.WriteString(c.SubQuery.String())
16081611
}
16091612
return builder.String()
@@ -1651,7 +1654,7 @@ type CreateView struct {
16511654
UUID *UUID
16521655
OnCluster *ClusterClause
16531656
TableSchema *TableSchemaClause
1654-
SubQuery *SubQueryClause
1657+
SubQuery *SubQuery
16551658
}
16561659

16571660
func (c *CreateView) Pos() Pos {
@@ -1689,6 +1692,7 @@ func (c *CreateView) String() string {
16891692
}
16901693

16911694
if c.SubQuery != nil {
1695+
builder.WriteString(" AS ")
16921696
builder.WriteString(c.SubQuery.String())
16931697
}
16941698
return builder.String()
@@ -4113,7 +4117,7 @@ type CreateLiveView struct {
41134117
Destination *DestinationClause
41144118
TableSchema *TableSchemaClause
41154119
WithTimeout *WithTimeoutClause
4116-
SubQuery *SubQueryClause
4120+
SubQuery *SubQuery
41174121
}
41184122

41194123
func (c *CreateLiveView) Type() string {
@@ -4157,6 +4161,7 @@ func (c *CreateLiveView) String() string {
41574161
}
41584162

41594163
if c.SubQuery != nil {
4164+
builder.WriteString(" AS ")
41604165
builder.WriteString(c.SubQuery.String())
41614166
}
41624167

@@ -5298,28 +5303,31 @@ func (s *SelectQuery) Accept(visitor ASTVisitor) error {
52985303
return visitor.VisitSelectQuery(s)
52995304
}
53005305

5301-
type SubQueryClause struct {
5302-
AsPos Pos
5303-
Select *SelectQuery
5306+
type SubQuery struct {
5307+
HasParen bool
5308+
Select *SelectQuery
53045309
}
53055310

5306-
func (s *SubQueryClause) Pos() Pos {
5307-
return s.AsPos
5311+
func (s *SubQuery) Pos() Pos {
5312+
return s.Select.Pos()
53085313
}
53095314

5310-
func (s *SubQueryClause) End() Pos {
5315+
func (s *SubQuery) End() Pos {
53115316
return s.Select.End()
53125317
}
53135318

5314-
func (s *SubQueryClause) String() string {
5315-
var builder strings.Builder
5316-
builder.WriteString(" AS (")
5317-
builder.WriteString(s.Select.String())
5318-
builder.WriteString(")")
5319-
return builder.String()
5319+
func (s *SubQuery) String() string {
5320+
if s.HasParen {
5321+
var builder strings.Builder
5322+
builder.WriteString("(")
5323+
builder.WriteString(s.Select.String())
5324+
builder.WriteString(")")
5325+
return builder.String()
5326+
}
5327+
return s.Select.String()
53205328
}
53215329

5322-
func (s *SubQueryClause) Accept(visitor ASTVisitor) error {
5330+
func (s *SubQuery) Accept(visitor ASTVisitor) error {
53235331
visitor.enter(s)
53245332
defer visitor.leave(s)
53255333
if s.Select != nil {

parser/ast_visitor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ type ASTVisitor interface {
121121
VisitWindowFrameNumber(expr *WindowFrameNumber) error
122122
VisitArrayJoinExpr(expr *ArrayJoinClause) error
123123
VisitSelectQuery(expr *SelectQuery) error
124-
VisitSubQueryExpr(expr *SubQueryClause) error
124+
VisitSubQueryExpr(expr *SubQuery) error
125125
VisitNotExpr(expr *NotExpr) error
126126
VisitNegateExpr(expr *NegateExpr) error
127127
VisitGlobalInExpr(expr *GlobalInOperation) error
@@ -1006,7 +1006,7 @@ func (v *DefaultASTVisitor) VisitSelectQuery(expr *SelectQuery) error {
10061006
return nil
10071007
}
10081008

1009-
func (v *DefaultASTVisitor) VisitSubQueryExpr(expr *SubQueryClause) error {
1009+
func (v *DefaultASTVisitor) VisitSubQueryExpr(expr *SubQuery) error {
10101010
if v.Visit != nil {
10111011
return v.Visit(expr)
10121012
}

parser/lexer.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ type Token struct {
3636
QuoteType int
3737
}
3838

39+
func (t *Token) ToString() string {
40+
if t.Kind == TokenKeyword {
41+
return strings.ToUpper(t.String)
42+
}
43+
return t.String
44+
}
45+
3946
type Lexer struct {
4047
input string
4148
current int

parser/parser_column.go

Lines changed: 173 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,197 @@ import (
55
"strings"
66
)
77

8+
const (
9+
PrecedenceUnknown = iota
10+
PrecedenceOr
11+
PrecedenceAnd
12+
PrecedenceQuery
13+
PrecedenceNot
14+
PrecedenceGlobal
15+
PrecedenceIs
16+
PrecedenceCompare
17+
PrecedenceBetweenLike
18+
precedenceIn
19+
PrecedenceAddSub
20+
PrecedenceMulDivMod
21+
PrecedenceBracket
22+
PrecedenceArrow
23+
PrecedenceDoubleColon
24+
)
25+
826
func (p *Parser) tryParseColumnComment(pos Pos) (*StringLiteral, error) {
927
if p.tryConsumeKeyword(KeywordComment) == nil {
1028
return nil, nil // nolint
1129
}
1230
return p.parseString(pos)
1331
}
1432

33+
func (p *Parser) getNextPrecedence(pos Pos) int {
34+
switch {
35+
case p.matchKeyword(KeywordOr):
36+
return PrecedenceOr
37+
case p.matchKeyword(KeywordAnd):
38+
return PrecedenceAnd
39+
case p.matchKeyword(KeywordIs):
40+
return PrecedenceIs
41+
case p.matchKeyword(KeywordNot):
42+
return PrecedenceNot
43+
case p.matchTokenKind(opTypeCast):
44+
return PrecedenceDoubleColon
45+
case p.matchTokenKind(opTypeEQ), p.matchTokenKind(opTypeLT), p.matchTokenKind(opTypeLE),
46+
p.matchTokenKind(opTypeGE), p.matchTokenKind(opTypeGT), p.matchTokenKind(opTypeDoubleEQ),
47+
p.matchTokenKind(opTypeNE), p.matchTokenKind("<>"):
48+
return PrecedenceCompare
49+
case p.matchTokenKind(opTypePlus), p.matchTokenKind(opTypeMinus):
50+
return PrecedenceAddSub
51+
case p.matchTokenKind(opTypeMul), p.matchTokenKind(opTypeDiv), p.matchTokenKind(opTypeMod):
52+
return PrecedenceMulDivMod
53+
case p.matchTokenKind(opTypeArrow):
54+
return PrecedenceArrow
55+
case p.matchTokenKind("("), p.matchTokenKind("["):
56+
return PrecedenceBracket
57+
case p.matchTokenKind(opTypeCast):
58+
return PrecedenceDoubleColon
59+
case p.matchKeyword(KeywordBetween), p.matchKeyword(KeywordLike), p.matchKeyword(KeywordIlike):
60+
return PrecedenceBetweenLike
61+
case p.matchKeyword(KeywordIn):
62+
return precedenceIn
63+
case p.matchKeyword(KeywordGlobal):
64+
return PrecedenceGlobal
65+
case p.matchTokenKind(opTypeQuery):
66+
return PrecedenceQuery
67+
default:
68+
return PrecedenceUnknown
69+
}
70+
}
71+
72+
func (p *Parser) parseInfix(expr Expr, precedence int) (Expr, error) {
73+
switch {
74+
case p.matchTokenKind(opTypeEQ), p.matchTokenKind(opTypeLT), p.matchTokenKind(opTypeLE),
75+
p.matchTokenKind(opTypeGE), p.matchTokenKind(opTypeGT),
76+
p.matchTokenKind(opTypeNE), p.matchTokenKind("<>"),
77+
p.matchTokenKind(opTypeMinus), p.matchTokenKind(opTypePlus), p.matchTokenKind(opTypeMul),
78+
p.matchTokenKind(opTypeDiv), p.matchTokenKind(opTypeMod),
79+
p.matchKeyword(KeywordIn), p.matchKeyword(KeywordLike),
80+
p.matchKeyword(KeywordIlike), p.matchKeyword(KeywordAnd), p.matchKeyword(KeywordOr),
81+
p.matchTokenKind(opTypeCast), p.matchTokenKind(opTypeArrow), p.matchTokenKind(opTypeDoubleEQ):
82+
op := p.last().ToString()
83+
_ = p.lexer.consumeToken()
84+
rightExpr, err := p.parseSubExpr(p.Pos(), precedence)
85+
if err != nil {
86+
return nil, err
87+
}
88+
return &BinaryOperation{
89+
LeftExpr: expr,
90+
Operation: TokenKind(op),
91+
RightExpr: rightExpr,
92+
}, nil
93+
case p.matchKeyword(KeywordGlobal):
94+
_ = p.lexer.consumeToken()
95+
if p.consumeKeyword(KeywordIn) != nil {
96+
return nil, fmt.Errorf("expected IN after GLOBAL, got %s", p.lastTokenKind())
97+
}
98+
rightExpr, err := p.parseSubExpr(p.Pos(), precedence)
99+
if err != nil {
100+
return nil, err
101+
}
102+
return &BinaryOperation{
103+
LeftExpr: expr,
104+
Operation: "GLOBAL IN",
105+
RightExpr: rightExpr,
106+
}, nil
107+
108+
case p.matchKeyword(KeywordNot):
109+
_ = p.lexer.consumeToken()
110+
switch {
111+
case p.matchKeyword(KeywordIn):
112+
case p.matchKeyword(KeywordLike):
113+
case p.matchKeyword(KeywordIlike):
114+
case p.matchKeyword(KeywordBetween):
115+
default:
116+
return nil, fmt.Errorf("expected IN, LIKE, ILIKE or BETWEEN after NOT, got %s", p.lastTokenKind())
117+
}
118+
op := p.last().ToString()
119+
_ = p.lexer.consumeToken()
120+
rightExpr, err := p.parseSubExpr(p.Pos(), precedence)
121+
if err != nil {
122+
return nil, err
123+
}
124+
return &BinaryOperation{
125+
LeftExpr: expr,
126+
Operation: TokenKind("NOT " + op),
127+
RightExpr: rightExpr,
128+
}, nil
129+
case p.matchTokenKind("["):
130+
params, err := p.parseArrayParams(p.Pos())
131+
if err != nil {
132+
return nil, err
133+
}
134+
return &ObjectParams{
135+
Object: expr,
136+
Params: params,
137+
}, nil
138+
case p.matchTokenKind(opTypeQuery):
139+
return p.parseTernaryExpr(expr)
140+
case p.matchKeyword(KeywordIs):
141+
_ = p.lexer.consumeToken()
142+
isNotNull := p.tryConsumeKeyword(KeywordNot) != nil
143+
if err := p.consumeKeyword(KeywordNull); err != nil {
144+
return nil, err
145+
}
146+
if isNotNull {
147+
return &IsNotNullExpr{
148+
IsPos: p.Pos(),
149+
Expr: expr,
150+
}, nil
151+
}
152+
return &IsNullExpr{
153+
IsPos: p.Pos(),
154+
Expr: expr,
155+
}, nil
156+
default:
157+
return nil, fmt.Errorf("unexpected token kind: %s", p.lastTokenKind())
158+
}
159+
}
160+
15161
func (p *Parser) parseExpr(pos Pos) (Expr, error) {
16-
orExpr, err := p.parseOrExpr(pos)
162+
expr, err := p.parseSubExpr(pos, PrecedenceUnknown)
17163
if err != nil {
18-
return orExpr, err
164+
return nil, err
19165
}
20-
switch {
21-
case p.matchKeyword(KeywordAs): // syntax: columnExpr (alias | AS identifier)
166+
if p.matchKeyword(KeywordAs) {
167+
pos := p.Pos()
22168
_ = p.lexer.consumeToken()
23169
alias, err := p.parseIdent()
24170
if err != nil {
25171
return nil, err
26172
}
27173
return &AliasExpr{
28-
AliasPos: alias.Pos(),
29-
Expr: orExpr,
174+
AliasPos: pos,
175+
Expr: expr,
30176
Alias: alias,
31177
}, nil
32178
}
33-
return orExpr, nil
179+
return expr, nil
180+
}
181+
182+
func (p *Parser) parseSubExpr(pos Pos, precedence int) (Expr, error) {
183+
expr, err := p.parseUnaryExpr(pos)
184+
if err != nil {
185+
return nil, err
186+
}
187+
for !p.lexer.isEOF() {
188+
nextPrecedence := p.getNextPrecedence(p.Pos())
189+
if nextPrecedence <= precedence {
190+
return expr, nil
191+
}
192+
// parse binary operation
193+
expr, err = p.parseInfix(expr, nextPrecedence)
194+
if err != nil {
195+
return nil, err
196+
}
197+
}
198+
return expr, nil
34199
}
35200

36201
func (p *Parser) parseOrExpr(pos Pos) (Expr, error) {
@@ -365,7 +530,7 @@ func (p *Parser) parseColumnExpr(pos Pos) (Expr, error) { //nolint:funlen
365530
case p.matchTokenKind("("):
366531
if peek, _ := p.lexer.peekToken(); peek != nil {
367532
if peek.Kind == TokenKeyword && strings.EqualFold(peek.String, KeywordSelect) {
368-
return p.parseSelectQuery(pos)
533+
return p.parseSubQuery(pos)
369534
}
370535
}
371536
return p.parseFunctionParams(p.Pos())

parser/parser_query.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ func (p *Parser) parseTableExpr(pos Pos) (*TableExpr, error) {
304304
}
305305
}
306306
case p.matchTokenKind("("):
307-
expr, err = p.parseSelectQuery(p.Pos())
307+
expr, err = p.parseSubQuery(p.Pos())
308308
default:
309309
return nil, errors.New("expect table name or subquery")
310310
}
@@ -729,19 +729,23 @@ func (p *Parser) parseHavingClause(pos Pos) (*HavingClause, error) {
729729
}, nil
730730
}
731731

732-
func (p *Parser) parseSubQueryClause(pos Pos) (*SubQueryClause, error) {
733-
if err := p.consumeKeyword(KeywordAs); err != nil {
734-
return nil, err
735-
}
732+
func (p *Parser) parseSubQuery(pos Pos) (*SubQuery, error) {
733+
734+
hasParen := p.tryConsumeTokenKind("(") != nil
736735

737736
selectQuery, err := p.parseSelectQuery(p.Pos())
738737
if err != nil {
739738
return nil, err
740739
}
740+
if hasParen {
741+
if _, err := p.consumeTokenKind(")"); err != nil {
742+
return nil, err
743+
}
744+
}
741745

742-
return &SubQueryClause{
743-
AsPos: pos,
744-
Select: selectQuery,
746+
return &SubQuery{
747+
HasParen: hasParen,
748+
Select: selectQuery,
745749
}, nil
746750
}
747751

0 commit comments

Comments
 (0)