parseEscape parses a backslash escape.
()
| 19 | |
| 20 | // parseEscape parses a backslash escape. |
| 21 | func (p *parser) parseEscape() (result string, err error) { |
| 22 | if len(p.s) < p.i+2 || p.s[p.i] != '\\' { |
| 23 | return "", errors.New("invalid escape sequence") |
| 24 | } |
| 25 | |
| 26 | start := p.i + 1 |
| 27 | c := p.s[start] |
| 28 | switch { |
| 29 | case c == '\r' || c == '\n' || c == '\f': |
| 30 | return "", errors.New("escaped line ending outside string") |
| 31 | case hexDigit(c): |
| 32 | // unicode escape (hex) |
| 33 | var i int |
| 34 | for i = start; i < p.i+6 && i < len(p.s) && hexDigit(p.s[i]); i++ { |
| 35 | // empty |
| 36 | } |
| 37 | v, _ := strconv.ParseUint(p.s[start:i], 16, 21) |
| 38 | if len(p.s) > i { |
| 39 | switch p.s[i] { |
| 40 | case '\r': |
| 41 | i++ |
| 42 | if len(p.s) > i && p.s[i] == '\n' { |
| 43 | i++ |
| 44 | } |
| 45 | case ' ', '\t', '\n', '\f': |
| 46 | i++ |
| 47 | } |
| 48 | } |
| 49 | p.i = i |
| 50 | return string(rune(v)), nil |
| 51 | } |
| 52 | |
| 53 | // Return the literal character after the backslash. |
| 54 | result = p.s[start : start+1] |
| 55 | p.i += 2 |
| 56 | return result, nil |
| 57 | } |
| 58 | |
| 59 | func hexDigit(c byte) bool { |
| 60 | return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' |
no test coverage detected