readTripleQuotedString reads a triple-quoted string (e.g. "'abc"' or """abc""")
(quote rune)
| 1074 | |
| 1075 | // readTripleQuotedString reads a triple-quoted string (e.g. "'abc"' or """abc""") |
| 1076 | func (t *Tokenizer) readTripleQuotedString(quote rune) (models.Token, error) { |
| 1077 | // Store start position for error reporting |
| 1078 | startPos := t.pos |
| 1079 | |
| 1080 | // Skip opening triple quotes |
| 1081 | for i := 0; i < 3; i++ { |
| 1082 | r, size := utf8.DecodeRune(t.input[t.pos.Index:]) |
| 1083 | t.pos.AdvanceRune(r, size) |
| 1084 | } |
| 1085 | |
| 1086 | var buf bytes.Buffer |
| 1087 | for t.pos.Index < len(t.input) { |
| 1088 | // Check for closing triple quotes |
| 1089 | if t.pos.Index+2 < len(t.input) { |
| 1090 | r1, s1 := utf8.DecodeRune(t.input[t.pos.Index:]) |
| 1091 | r2, s2 := utf8.DecodeRune(t.input[t.pos.Index+s1:]) |
| 1092 | r3, s3 := utf8.DecodeRune(t.input[t.pos.Index+s1+s2:]) |
| 1093 | if r1 == quote && r2 == quote && r3 == quote { |
| 1094 | // Skip closing quotes |
| 1095 | t.pos.Index += s1 + s2 + s3 |
| 1096 | t.pos.Column += 3 |
| 1097 | |
| 1098 | value := buf.String() |
| 1099 | if quote == '\'' { |
| 1100 | return models.Token{ |
| 1101 | Type: models.TokenTypeTripleSingleQuotedString, |
| 1102 | Value: value, |
| 1103 | Quote: quote, |
| 1104 | }, nil |
| 1105 | } |
| 1106 | return models.Token{ |
| 1107 | Type: models.TokenTypeTripleDoubleQuotedString, |
| 1108 | Value: value, |
| 1109 | Quote: quote, |
| 1110 | }, nil |
| 1111 | } |
| 1112 | } |
| 1113 | |
| 1114 | // Handle regular characters |
| 1115 | r, size := utf8.DecodeRune(t.input[t.pos.Index:]) |
| 1116 | if r == '\n' { |
| 1117 | buf.WriteRune(r) |
| 1118 | t.pos.Index += size |
| 1119 | t.pos.Line++ |
| 1120 | t.pos.Column = 1 |
| 1121 | continue |
| 1122 | } |
| 1123 | |
| 1124 | buf.WriteRune(r) |
| 1125 | t.pos.Index += size |
| 1126 | t.pos.Column++ |
| 1127 | } |
| 1128 | |
| 1129 | return models.Token{}, errors.UnterminatedStringError( |
| 1130 | t.toSQLPosition(startPos), |
| 1131 | string(t.input), |
| 1132 | ) |
| 1133 | } |
no test coverage detected