...
1 package syntax
2
3 import (
4 "bytes"
5 "strconv"
6 "strings"
7 "unicode"
8 )
9
10 func Escape(input string) string {
11 b := &bytes.Buffer{}
12 for _, r := range input {
13 escape(b, r, false)
14 }
15 return b.String()
16 }
17
18 const meta = `\.+*?()|[]{}^$# `
19
20 func escape(b *bytes.Buffer, r rune, force bool) {
21 if unicode.IsPrint(r) {
22 if strings.IndexRune(meta, r) >= 0 || force {
23 b.WriteRune('\\')
24 }
25 b.WriteRune(r)
26 return
27 }
28
29 switch r {
30 case '\a':
31 b.WriteString(`\a`)
32 case '\f':
33 b.WriteString(`\f`)
34 case '\n':
35 b.WriteString(`\n`)
36 case '\r':
37 b.WriteString(`\r`)
38 case '\t':
39 b.WriteString(`\t`)
40 case '\v':
41 b.WriteString(`\v`)
42 default:
43 if r < 0x100 {
44 b.WriteString(`\x`)
45 s := strconv.FormatInt(int64(r), 16)
46 if len(s) == 1 {
47 b.WriteRune('0')
48 }
49 b.WriteString(s)
50 break
51 }
52 b.WriteString(`\u`)
53 b.WriteString(strconv.FormatInt(int64(r), 16))
54 }
55 }
56
57 func Unescape(input string) (string, error) {
58 idx := strings.IndexRune(input, '\\')
59
60 if idx == -1 {
61 return input, nil
62 }
63
64 buf := bytes.NewBufferString(input[:idx])
65
66
67 p := parser{}
68 p.setPattern(input[idx+1:])
69 for {
70 if p.rightMost() {
71 return "", p.getErr(ErrIllegalEndEscape)
72 }
73 r, err := p.scanCharEscape()
74 if err != nil {
75 return "", err
76 }
77 buf.WriteRune(r)
78
79 if p.rightMost() {
80 return buf.String(), nil
81 }
82
83 r = p.moveRightGetChar()
84 for r != '\\' {
85 buf.WriteRune(r)
86 if p.rightMost() {
87
88 return buf.String(), nil
89 }
90
91 r = p.moveRightGetChar()
92 }
93 }
94 }
95
View as plain text