@@ -57,6 +57,12 @@ class SQL < Scanner
57
57
58
58
STRING_PREFIXES = /[xnb]|_\w +/i
59
59
60
+ STRING_CONTENT_PATTERN = {
61
+ '"' => / (?: [^\\ "] | "" )+ /x ,
62
+ "'" => / (?: [^\\ '] | '' )+ /x ,
63
+ '`' => / (?: [^\\ `] | `` )+ /x ,
64
+ }
65
+
60
66
def scan_tokens encoder , options
61
67
62
68
state = :initial
@@ -90,7 +96,7 @@ def scan_tokens encoder, options
90
96
state = :string
91
97
encoder . text_token match , :delimiter
92
98
93
- elsif match = scan ( / @? [A-Za-z_][A-Za-z_0-9]* /x )
99
+ elsif match = scan ( / @? [A-Za-z_][A-Za-z_0-9\$ ]* /x )
94
100
encoder . text_token match , name_expected ? :ident : ( match [ 0 ] == ?@ ? :variable : IDENT_KIND [ match ] )
95
101
name_expected = false
96
102
@@ -115,40 +121,26 @@ def scan_tokens encoder, options
115
121
end
116
122
117
123
elsif state == :string
118
- if match = scan ( /[^\\ "'`]+/ )
119
- string_content << match
120
- next
124
+ if match = scan ( STRING_CONTENT_PATTERN [ string_type ] )
125
+ encoder . text_token match , :content
121
126
elsif match = scan ( /["'`]/ )
122
127
if string_type == match
123
128
if peek ( 1 ) == string_type # doubling means escape
124
- string_content << string_type << getch
125
- next
126
- end
127
- unless string_content . empty?
128
- encoder . text_token string_content , :content
129
- string_content = ''
129
+ encoder . text_token match + getch , :content
130
+ else
131
+ encoder . text_token match , :delimiter
132
+ encoder . end_group :string
133
+ state = :initial
134
+ string_type = nil
130
135
end
131
- encoder . text_token match , :delimiter
132
- encoder . end_group :string
133
- state = :initial
134
- string_type = nil
135
136
else
136
- string_content << match
137
+ encoder . text_token match , :content
137
138
end
138
139
elsif match = scan ( / \\ (?: #{ ESCAPE } | #{ UNICODE_ESCAPE } ) /mox )
139
- unless string_content . empty?
140
- encoder . text_token string_content , :content
141
- string_content = ''
142
- end
143
140
encoder . text_token match , :char
144
141
elsif match = scan ( / \\ . /mox )
145
- string_content << match
146
- next
142
+ encoder . text_token match , :content
147
143
elsif match = scan ( / \\ | $ /x )
148
- unless string_content . empty?
149
- encoder . text_token string_content , :content
150
- string_content = ''
151
- end
152
144
encoder . text_token match , :error unless match . empty?
153
145
encoder . end_group :string
154
146
state = :initial
0 commit comments