Skip to content

Commit f304b1d

Browse files
kyleconroyclaude
andcommitted
Support underscores in binary and octal literals
Added support for underscore digit separators in binary literals (0b0010_0100_0111) and octal literals (0o755_644) to match ClickHouse's behavior for numeric literals with underscores. Updated both readNumber and readNumberOrIdent functions in the lexer to handle underscores in binary and octal number formats. Fixes stmt6 in 02354_numeric_literals_with_underscores. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 2fa01e3 commit f304b1d

File tree

2 files changed

+9
-12
lines changed

2 files changed

+9
-12
lines changed

lexer/lexer.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -886,19 +886,19 @@ func (l *Lexer) readNumber() Item {
886886
}
887887
return Item{Token: token.NUMBER, Value: sb.String(), Pos: pos}
888888
} else if l.ch == 'b' || l.ch == 'B' {
889-
// Binary literal
889+
// Binary literal (allows underscores as digit separators: 0b0010_0100_0111)
890890
sb.WriteRune(l.ch)
891891
l.readChar()
892-
for l.ch == '0' || l.ch == '1' {
892+
for l.ch == '0' || l.ch == '1' || l.ch == '_' {
893893
sb.WriteRune(l.ch)
894894
l.readChar()
895895
}
896896
return Item{Token: token.NUMBER, Value: sb.String(), Pos: pos}
897897
} else if l.ch == 'o' || l.ch == 'O' {
898-
// Octal literal
898+
// Octal literal (allows underscores as digit separators: 0o755_644)
899899
sb.WriteRune(l.ch)
900900
l.readChar()
901-
for l.ch >= '0' && l.ch <= '7' {
901+
for (l.ch >= '0' && l.ch <= '7') || l.ch == '_' {
902902
sb.WriteRune(l.ch)
903903
l.readChar()
904904
}
@@ -1088,9 +1088,10 @@ func (l *Lexer) readNumberOrIdent() Item {
10881088
}
10891089
}
10901090
} else if val == "0" && (l.ch == 'b' || l.ch == 'B') && (l.peekChar() == '0' || l.peekChar() == '1') {
1091+
// Binary literal (allows underscores as digit separators: 0b0010_0100_0111)
10911092
sb.WriteRune(l.ch)
10921093
l.readChar()
1093-
for l.ch == '0' || l.ch == '1' {
1094+
for l.ch == '0' || l.ch == '1' || l.ch == '_' {
10941095
sb.WriteRune(l.ch)
10951096
l.readChar()
10961097
}
@@ -1100,11 +1101,11 @@ func (l *Lexer) readNumberOrIdent() Item {
11001101
// and the number already consumed is just the leading zero (checking for 0x, 0b, 0o)
11011102
if startCh == '0' && len(sb.String()) == 1 {
11021103
// Already handled above for 0x, 0b
1103-
// Handle 0o for octal
1104+
// Handle 0o for octal (allows underscores as digit separators: 0o755_644)
11041105
if l.ch == 'o' || l.ch == 'O' {
11051106
sb.WriteRune(l.ch)
11061107
l.readChar()
1107-
for l.ch >= '0' && l.ch <= '7' {
1108+
for (l.ch >= '0' && l.ch <= '7') || l.ch == '_' {
11081109
sb.WriteRune(l.ch)
11091110
l.readChar()
11101111
}
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt6": true
4-
}
5-
}
1+
{}

0 commit comments

Comments
 (0)