@@ -57,6 +57,12 @@ class SQL < Scanner
5757
5858STRING_PREFIXES = /[xnb]|_\w +/i
5959
60+ STRING_CONTENT_PATTERN = {
61+ '"' => / (?: [^\\ "] | "" )+ /x ,
62+ "'" => / (?: [^\\ '] | '' )+ /x ,
63+ '`' => / (?: [^\\ `] | `` )+ /x ,
64+ }
65+
6066def scan_tokens encoder , options
6167
6268state = :initial
@@ -115,40 +121,26 @@ def scan_tokens encoder, options
115121end
116122
117123elsif 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
121126elsif match = scan ( /["'`]/ )
122127if string_type ==match
123128if 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
130135end
131- encoder . text_token match , :delimiter
132- encoder . end_group :string
133- state = :initial
134- string_type = nil
135136else
136- string_content << match
137+ encoder . text_token match , :content
137138end
138139elsif match = scan ( /\\ (?:#{ ESCAPE } |#{ UNICODE_ESCAPE } ) /mox )
139- unless string_content . empty?
140- encoder . text_token string_content , :content
141- string_content = ''
142- end
143140encoder . text_token match , :char
144141elsif match = scan ( /\\ . /mox )
145- string_content <<match
146- next
142+ encoder . text_token match , :content
147143elsif match = scan ( /\\ | $ /x )
148- unless string_content . empty?
149- encoder . text_token string_content , :content
150- string_content = ''
151- end
152144encoder . text_token match , :error unless match . empty?
153145encoder . end_group :string
154146state = :initial