Skip to content

Commit a71dd54

Browse files
committed
Escape characters
1 parent ec069ab commit a71dd54

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

Sources/Compiler/Parse/Lexer.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ struct Lexer {
124124
case ("^", _): return consumeSingle(of: .carrot)
125125
case ("~", _): return consumeSingle(of: .tilde)
126126
case ("'", _): return parseString()
127+
case ("\"", _): return parseEscapedIdentifier(closing: "\"")
128+
case ("[", _): return parseEscapedIdentifier(closing: "]")
129+
case ("`", _): return parseEscapedIdentifier(closing: "`")
127130
default:
128131
diagnostics.add(.init(
129132
"Unexpected character: '\(current)'",
@@ -149,6 +152,35 @@ struct Lexer {
149152
}
150153
}
151154

155+
// SQLite does not seem to really care what goes between the escape delimiters.
156+
// Table names will gladly take newlines and such.
157+
private mutating func parseEscapedIdentifier(closing: Character) -> Token {
158+
let tokenStart = startLocation()
159+
advance() // Opening
160+
let identifierStart = currentIndex
161+
162+
while let current, current != closing {
163+
advance()
164+
}
165+
166+
let identifierEnd = currentIndex
167+
168+
// If the current is nil it the EOF, else its
169+
// our closing character.
170+
if current == nil {
171+
diagnostics.add(.init(
172+
"Unterminated escaped identifier",
173+
at: location(from: tokenStart)
174+
))
175+
} else {
176+
advance()
177+
}
178+
179+
let location = location(from: tokenStart)
180+
let identifierRange = identifierStart..<identifierEnd
181+
return Token(kind: .symbol(source[identifierRange]), location: location)
182+
}
183+
152184
private mutating func parseWord() -> Token {
153185
let start = startLocation()
154186

Tests/CompilerTests/Compiler/CompileCreateTable.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,14 @@ CREATE TABLE qux (
6363
bar INTEGER,
6464
PRIMARY KEY (bar)
6565
) STRICT;
66+
67+
-- CHECK: TABLE
68+
-- CHECK: NAME PRIMARY
69+
-- CHECK: COLUMNS
70+
-- CHECK: KEY TABLE
71+
-- CHECK: VALUE KEY?
72+
-- CHECK: KIND normal
73+
CREATE TABLE "PRIMARY" (
74+
"TABLE" INTEGER,
75+
[TABLE] `KEY`
76+
) STRICT;

0 commit comments

Comments
 (0)