Skip to content

Commit f275ecf

Browse files
committed
fix: Parsing bugs (as always) via some nice little tests
1 parent 421845e commit f275ecf

File tree

4 files changed

+75
-11
lines changed

4 files changed

+75
-11
lines changed

glint/src/main/java/co/clflushopt/glint/sql/Parser.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Arrays;
55
import java.util.Collections;
66
import java.util.List;
7+
import java.util.logging.Level;
78
import java.util.logging.Logger;
89

910
public class Parser {
@@ -13,6 +14,11 @@ public class Parser {
1314

1415
public Parser(TokenStream tokens) {
1516
this.tokens = tokens;
17+
logger.setLevel(Level.FINE);
18+
}
19+
20+
public SqlExpression parse() {
21+
return parse(0);
1622
}
1723

1824
public int nextPrecedence() {
@@ -253,7 +259,7 @@ protected SqlExpression parse(int precedence) {
253259
}
254260

255261
while (precedence < nextPrecedence()) {
256-
left = parseInfix(left, precedence);
262+
left = parseInfix(left, nextPrecedence());
257263
}
258264

259265
return left;

glint/src/main/java/co/clflushopt/glint/sql/SqlBinaryExpression.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public SqlExpression getRight() {
3131

3232
@Override
3333
public String toString() {
34-
return left + " " + operator + " " + right;
34+
return "(" + left + " " + operator + " " + right + ")";
3535
}
3636

3737
@Override
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package co.clflushopt.glint.sql;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertTrue;
5+
6+
import java.util.List;
7+
8+
import org.junit.Test;
9+
10+
public class ParserTest {
11+
12+
@Test
13+
public void canParseArithmeticExpressions() {
14+
var sql = "1 + 2 * 3";
15+
var tokens = new Tokenizer(sql).tokenize();
16+
var actual = new Parser(tokens).parse();
17+
var expected = new SqlBinaryExpression(new SqlLong(1), "+",
18+
new SqlBinaryExpression(new SqlLong(2), "*", new SqlLong(3)));
19+
20+
assertEquals(actual, expected);
21+
}
22+
23+
@Test
24+
public void canParseArithmeticExpressionWithLeftPrec() {
25+
var sql = "1 * 2 + 3";
26+
var tokens = new Tokenizer(sql).tokenize();
27+
var actual = new Parser(tokens).parse();
28+
var expected = new SqlBinaryExpression(
29+
new SqlBinaryExpression(new SqlLong(1), "*", new SqlLong(2)), "+", new SqlLong(3));
30+
31+
assertEquals(actual, expected);
32+
}
33+
34+
@Test
35+
public void canParseSimpleSelectStatement() {
36+
var sql = "SELECT id, first_name FROM employees";
37+
var tokens = new Tokenizer(sql).tokenize();
38+
var actual = new Parser(tokens).parse();
39+
assertTrue(actual instanceof SqlSelect);
40+
var select = (SqlSelect) actual;
41+
assertEquals(select.getTableName(), "employees");
42+
assertEquals(select.getProjection(),
43+
List.of(new SqlIdentifier("id"), new SqlIdentifier("first_name")));
44+
}
45+
46+
@Test
47+
public void canParseSelectStatementWithBinaryExpression() {
48+
var sql = "SELECT salary * 0.1 FROM employees";
49+
var tokens = new Tokenizer(sql).tokenize();
50+
var actual = new Parser(tokens).parse();
51+
assertTrue(actual instanceof SqlSelect);
52+
var select = (SqlSelect) actual;
53+
assertEquals(select.getTableName(), "employees");
54+
assertEquals(select.getProjection(), List
55+
.of(new SqlBinaryExpression(new SqlIdentifier("salary"), "*", new SqlDouble(0.1))));
56+
57+
}
58+
}

glint/src/test/java/co/clflushopt/glint/sql/TokenizerTest.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
public class TokenizerTest {
1111

1212
@Test
13-
public void testTokenizeSimpleSelect() {
13+
public void canTokenizeSimpleSelect() {
1414
List<Token> expected = Arrays.asList(new Token("SELECT", Keyword.SELECT, 6),
1515
new Token("id", Literal.IDENTIFIER, 9), new Token(",", Symbol.COMMA, 10),
1616
new Token("first_name", Literal.IDENTIFIER, 21), new Token(",", Symbol.COMMA, 22),
@@ -24,7 +24,7 @@ public void testTokenizeSimpleSelect() {
2424
}
2525

2626
@Test
27-
public void testProjectionWithBinaryExpression() {
27+
public void canTokenizeProjectionWithBinaryExpression() {
2828
List<Token> expected = Arrays.asList(new Token("SELECT", Keyword.SELECT, 6),
2929
new Token("salary", Literal.IDENTIFIER, 13), new Token("*", Symbol.STAR, 15),
3030
new Token("0.1", Literal.DOUBLE, 19), new Token("FROM", Keyword.FROM, 24),
@@ -51,7 +51,7 @@ public void testProjectionWithAliasedBinaryExpression() {
5151
}
5252

5353
@Test
54-
public void testTokenizeSelectWithWhere() {
54+
public void canTokenizeSelectWithWhere() {
5555
List<Token> expected = Arrays.asList(new Token("SELECT", Keyword.SELECT, 6),
5656
new Token("a", Literal.IDENTIFIER, 8), new Token(",", Symbol.COMMA, 9),
5757
new Token("b", Literal.IDENTIFIER, 11), new Token("FROM", Keyword.FROM, 16),
@@ -66,7 +66,7 @@ public void testTokenizeSelectWithWhere() {
6666
}
6767

6868
@Test
69-
public void testTokenizeSelectWithAggregates() {
69+
public void canTokenizeSelectWithAggregates() {
7070
List<Token> expected = Arrays.asList(new Token("SELECT", Keyword.SELECT, 6),
7171
new Token("state", Literal.IDENTIFIER, 12), new Token(",", Symbol.COMMA, 13),
7272
new Token("MAX", Keyword.MAX, 17), new Token("(", Symbol.LEFT_PAREN, 18),
@@ -82,7 +82,7 @@ public void testTokenizeSelectWithAggregates() {
8282
}
8383

8484
@Test
85-
public void testTokenizeSelectWithAggregatesAndHaving() {
85+
public void canTokenizeSelectWithAggregatesAndHaving() {
8686
List<Token> expected = Arrays.asList(new Token("SELECT", Keyword.SELECT, 6),
8787
new Token("state", Literal.IDENTIFIER, 12), new Token(",", Symbol.COMMA, 13),
8888
new Token("MAX", Keyword.MAX, 17), new Token("(", Symbol.LEFT_PAREN, 18),
@@ -102,7 +102,7 @@ public void testTokenizeSelectWithAggregatesAndHaving() {
102102
}
103103

104104
@Test
105-
public void testTokenizeCompoundOperators() {
105+
public void canTokenizeCompoundOperators() {
106106
List<Token> expected = Arrays.asList(new Token("a", Literal.IDENTIFIER, 1),
107107
new Token(">=", Symbol.GT_EQ, 4), new Token("b", Literal.IDENTIFIER, 6),
108108
new Token("OR", Keyword.OR, 9), new Token("a", Literal.IDENTIFIER, 11),
@@ -119,7 +119,7 @@ public void testTokenizeCompoundOperators() {
119119
}
120120

121121
@Test
122-
public void testTokenizeLongValues() {
122+
public void canTokenizeLongValues() {
123123
List<Token> expected = Arrays.asList(new Token("123456789", Literal.LONG, 9),
124124
new Token("+", Symbol.PLUS, 11), new Token("987654321", Literal.LONG, 21));
125125

@@ -129,7 +129,7 @@ public void testTokenizeLongValues() {
129129
}
130130

131131
@Test
132-
public void testTokenizeFloatDoubleValues() {
132+
public void canTokenizeFloatDoubleValues() {
133133
List<Token> expected = Arrays.asList(new Token("123456789.00", Literal.DOUBLE, 12),
134134
new Token("+", Symbol.PLUS, 14), new Token("987654321.001", Literal.DOUBLE, 28));
135135

@@ -139,7 +139,7 @@ public void testTokenizeFloatDoubleValues() {
139139
}
140140

141141
@Test
142-
public void testTokenizeTableGroup() {
142+
public void canTokenizeTableGroup() {
143143
List<Token> expected = Arrays.asList(new Token("select", Keyword.SELECT, 6),
144144
new Token("*", Symbol.STAR, 8), new Token("from", Keyword.FROM, 13),
145145
new Token("group", Literal.IDENTIFIER, 19));

0 commit comments

Comments
 (0)