annotate vendor/github.com/dlclark/regexp2/syntax/parser.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 package syntax
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 "fmt"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 "math"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 "os"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 "sort"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 "strconv"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9 "unicode"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 type RegexOptions int32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 IgnoreCase RegexOptions = 0x0001 // "i"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 Multiline = 0x0002 // "m"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17 ExplicitCapture = 0x0004 // "n"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 Compiled = 0x0008 // "c"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 Singleline = 0x0010 // "s"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 IgnorePatternWhitespace = 0x0020 // "x"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21 RightToLeft = 0x0040 // "r"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 Debug = 0x0080 // "d"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 ECMAScript = 0x0100 // "e"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24 RE2 = 0x0200 // RE2 compat mode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 func optionFromCode(ch rune) RegexOptions {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 // case-insensitive
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 case 'i', 'I':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 return IgnoreCase
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 case 'r', 'R':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 return RightToLeft
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 case 'm', 'M':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 return Multiline
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 case 'n', 'N':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 return ExplicitCapture
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 case 's', 'S':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 return Singleline
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 case 'x', 'X':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 return IgnorePatternWhitespace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 case 'd', 'D':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 return Debug
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 case 'e', 'E':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 return ECMAScript
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 // An Error describes a failure to parse a regular expression
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 // and gives the offending expression.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 type Error struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 Code ErrorCode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 Expr string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 Args []interface{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 func (e *Error) Error() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 if len(e.Args) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 return "error parsing regexp: " + e.Code.String() + " in `" + e.Expr + "`"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 return "error parsing regexp: " + fmt.Sprintf(e.Code.String(), e.Args...) + " in `" + e.Expr + "`"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 // An ErrorCode describes a failure to parse a regular expression.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 type ErrorCode string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 // internal issue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 ErrInternalError ErrorCode = "regexp/syntax: internal error"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 // Parser errors
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 ErrUnterminatedComment = "unterminated comment"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 ErrInvalidCharRange = "invalid character class range"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 ErrInvalidRepeatSize = "invalid repeat count"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 ErrInvalidUTF8 = "invalid UTF-8"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77 ErrCaptureGroupOutOfRange = "capture group number out of range"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 ErrUnexpectedParen = "unexpected )"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79 ErrMissingParen = "missing closing )"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 ErrMissingBrace = "missing closing }"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 ErrInvalidRepeatOp = "invalid nested repetition operator"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 ErrMissingRepeatArgument = "missing argument to repetition operator"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 ErrConditionalExpression = "illegal conditional (?(...)) expression"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84 ErrTooManyAlternates = "too many | in (?()|)"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 ErrUnrecognizedGrouping = "unrecognized grouping construct: (%v"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 ErrInvalidGroupName = "invalid group name: group names must begin with a word character and have a matching terminator"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 ErrCapNumNotZero = "capture number cannot be zero"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 ErrUndefinedBackRef = "reference to undefined group number %v"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89 ErrUndefinedNameRef = "reference to undefined group name %v"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 ErrAlternationCantCapture = "alternation conditions do not capture and cannot be named"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 ErrAlternationCantHaveComment = "alternation conditions cannot be comments"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 ErrMalformedReference = "(?(%v) ) malformed"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 ErrUndefinedReference = "(?(%v) ) reference to undefined group"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94 ErrIllegalEndEscape = "illegal \\ at end of pattern"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 ErrMalformedSlashP = "malformed \\p{X} character escape"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 ErrIncompleteSlashP = "incomplete \\p{X} character escape"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 ErrUnknownSlashP = "unknown unicode category, script, or property '%v'"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 ErrUnrecognizedEscape = "unrecognized escape sequence \\%v"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 ErrMissingControl = "missing control character"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 ErrUnrecognizedControl = "unrecognized control character"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 ErrTooFewHex = "insufficient hexadecimal digits"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 ErrInvalidHex = "hex values may not be larger than 0x10FFFF"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 ErrMalformedNameRef = "malformed \\k<...> named back reference"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 ErrBadClassInCharRange = "cannot include class \\%v in character range"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 ErrUnterminatedBracket = "unterminated [] set"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 ErrSubtractionMustBeLast = "a subtraction must be the last element in a character class"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 ErrReversedCharRange = "[x-y] range in reverse order"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 func (e ErrorCode) String() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 return string(e)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 type parser struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 stack *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116 group *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 alternation *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 concatenation *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 unit *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 patternRaw string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 pattern []rune
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 currentPos int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 specialCase *unicode.SpecialCase
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 autocap int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 capcount int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 captop int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 capsize int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 caps map[int]int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 capnames map[string]int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 capnumlist []int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 capnamelist []string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 options RegexOptions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139 optionsStack []RegexOptions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 ignoreNextParen bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 maxValueDiv10 int = math.MaxInt32 / 10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 maxValueMod10 = math.MaxInt32 % 10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 // Parse converts a regex string into a parse tree
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 func Parse(re string, op RegexOptions) (*RegexTree, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 p := parser{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 options: op,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 caps: make(map[int]int),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 p.setPattern(re)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 if err := p.countCaptures(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 p.reset(op)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 root, err := p.scanRegex()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166 tree := &RegexTree{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 root: root,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 caps: p.caps,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 capnumlist: p.capnumlist,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 captop: p.captop,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 Capnames: p.capnames,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 Caplist: p.capnamelist,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 options: op,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 if tree.options&Debug > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 os.Stdout.WriteString(tree.Dump())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180 return tree, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 func (p *parser) setPattern(pattern string) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 p.patternRaw = pattern
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185 p.pattern = make([]rune, 0, len(pattern))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 //populate our rune array to handle utf8 encoding
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 for _, r := range pattern {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 p.pattern = append(p.pattern, r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192 func (p *parser) getErr(code ErrorCode, args ...interface{}) error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 return &Error{Code: code, Expr: p.patternRaw, Args: args}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 func (p *parser) noteCaptureSlot(i, pos int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 if _, ok := p.caps[i]; !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 // the rhs of the hashtable isn't used in the parser
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 p.caps[i] = pos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200 p.capcount++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202 if p.captop <= i {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203 if i == math.MaxInt32 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 p.captop = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 p.captop = i + 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 func (p *parser) noteCaptureName(name string, pos int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 if p.capnames == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214 p.capnames = make(map[string]int)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 if _, ok := p.capnames[name]; !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 p.capnames[name] = pos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219 p.capnamelist = append(p.capnamelist, name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223 func (p *parser) assignNameSlots() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224 if p.capnames != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 for _, name := range p.capnamelist {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226 for p.isCaptureSlot(p.autocap) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 p.autocap++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229 pos := p.capnames[name]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230 p.capnames[name] = p.autocap
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 p.noteCaptureSlot(p.autocap, pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233 p.autocap++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237 // if the caps array has at least one gap, construct the list of used slots
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238 if p.capcount < p.captop {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 p.capnumlist = make([]int, p.capcount)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 for k := range p.caps {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243 p.capnumlist[i] = k
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244 i++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247 sort.Ints(p.capnumlist)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250 // merge capsnumlist into capnamelist
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 if p.capnames != nil || p.capnumlist != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252 var oldcapnamelist []string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 var next int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 var k int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256 if p.capnames == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257 oldcapnamelist = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 p.capnames = make(map[string]int)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 p.capnamelist = []string{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 next = -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262 oldcapnamelist = p.capnamelist
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263 p.capnamelist = []string{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264 next = p.capnames[oldcapnamelist[0]]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 for i := 0; i < p.capcount; i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268 j := i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 if p.capnumlist != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270 j = p.capnumlist[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 if next == j {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274 p.capnamelist = append(p.capnamelist, oldcapnamelist[k])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275 k++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 if k == len(oldcapnamelist) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278 next = -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280 next = p.capnames[oldcapnamelist[k]]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 //feature: culture?
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285 str := strconv.Itoa(j)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286 p.capnamelist = append(p.capnamelist, str)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 p.capnames[str] = j
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293 func (p *parser) consumeAutocap() int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294 r := p.autocap
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295 p.autocap++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296 return r
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299 // CountCaptures is a prescanner for deducing the slots used for
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300 // captures by doing a partial tokenization of the pattern.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 func (p *parser) countCaptures() error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302 var ch rune
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 p.noteCaptureSlot(0, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 p.autocap = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 pos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312 case '\\':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313 if p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314 p.scanBackslash(true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317 case '#':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318 if p.useOptionX() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320 p.scanBlank()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323 case '[':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324 p.scanCharSet(false, true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 case ')':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327 if !p.emptyOptionsStack() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 p.popOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331 case '(':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332 if p.charsRight() >= 2 && p.rightChar(1) == '#' && p.rightChar(0) == '?' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 p.scanBlank()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 p.pushOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337 if p.charsRight() > 0 && p.rightChar(0) == '?' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 // we have (?...
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341 if p.charsRight() > 1 && (p.rightChar(0) == '<' || p.rightChar(0) == '\'') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 // named group: (?<... or (?'...
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 if ch != '0' && IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348 if ch >= '1' && ch <= '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349 dec, err := p.scanDecimal()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 return err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353 p.noteCaptureSlot(dec, pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355 p.noteCaptureName(p.scanCapname(), pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
356 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
357 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
358 } else if p.useRE2() && p.charsRight() > 2 && (p.rightChar(0) == 'P' && p.rightChar(1) == '<') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
359 // RE2-compat (?P<)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
360 p.moveRight(2)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
361 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
362 if IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
363 p.noteCaptureName(p.scanCapname(), pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
364 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
365
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
366 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
367 // (?...
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
368
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
369 // get the options if it's an option construct (?cimsx-cimsx...)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
370 p.scanOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
371
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
372 if p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
373 if p.rightChar(0) == ')' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
374 // (?cimsx-cimsx)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
375 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
376 p.popKeepOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
377 } else if p.rightChar(0) == '(' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
378 // alternation construct: (?(foo)yes|no)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
379 // ignore the next paren so we don't capture the condition
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
380 p.ignoreNextParen = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
381
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
382 // break from here so we don't reset ignoreNextParen
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
383 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
384 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
385 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
386 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
387 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
388 if !p.useOptionN() && !p.ignoreNextParen {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
389 p.noteCaptureSlot(p.consumeAutocap(), pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
390 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
391 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
392 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
393
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
394 p.ignoreNextParen = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
395
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
396 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
397 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
398
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
399 p.assignNameSlots()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
400 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
401 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
402
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
403 func (p *parser) reset(topopts RegexOptions) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
404 p.currentPos = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
405 p.autocap = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
406 p.ignoreNextParen = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
407
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
408 if len(p.optionsStack) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
409 p.optionsStack = p.optionsStack[:0]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
410 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
411
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
412 p.options = topopts
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
413 p.stack = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
414 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
415
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
416 func (p *parser) scanRegex() (*regexNode, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
417 ch := '@' // nonspecial ch, means at beginning
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
418 isQuant := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
419
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
420 p.startGroup(newRegexNodeMN(ntCapture, p.options, 0, -1))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
421
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
422 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
423 wasPrevQuantifier := isQuant
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
424 isQuant = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
425
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
426 if err := p.scanBlank(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
427 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
428 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
429
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
430 startpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
431
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
432 // move past all of the normal characters. We'll stop when we hit some kind of control character,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
433 // or if IgnorePatternWhiteSpace is on, we'll stop when we see some whitespace.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
434 if p.useOptionX() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
435 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
436 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
437 //UGLY: clean up, this is ugly
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
438 if !(!isStopperX(ch) || (ch == '{' && !p.isTrueQuantifier())) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
439 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
440 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
441 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
442 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
443 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
444 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
445 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
446 if !(!isSpecial(ch) || ch == '{' && !p.isTrueQuantifier()) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
447 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
448 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
449 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
450 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
451 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
452
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
453 endpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
454
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
455 p.scanBlank()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
456
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
457 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
458 ch = '!' // nonspecial, means at end
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
459 } else if ch = p.rightChar(0); isSpecial(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
460 isQuant = isQuantifier(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
461 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
462 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
463 ch = ' ' // nonspecial, means at ordinary char
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
464 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
465
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
466 if startpos < endpos {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
467 cchUnquantified := endpos - startpos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
468 if isQuant {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
469 cchUnquantified--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
470 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
471 wasPrevQuantifier = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
472
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
473 if cchUnquantified > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
474 p.addToConcatenate(startpos, cchUnquantified, false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
475 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
476
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
477 if isQuant {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
478 p.addUnitOne(p.charAt(endpos - 1))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
479 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
480 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
481
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
482 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
483 case '!':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
484 goto BreakOuterScan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
485
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
486 case ' ':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
487 goto ContinueOuterScan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
488
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
489 case '[':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
490 cc, err := p.scanCharSet(p.useOptionI(), false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
491 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
492 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
493 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
494 p.addUnitSet(cc)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
495
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
496 case '(':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
497 p.pushOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
498
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
499 if grouper, err := p.scanGroupOpen(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
500 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
501 } else if grouper == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
502 p.popKeepOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
503 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
504 p.pushGroup()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
505 p.startGroup(grouper)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
506 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
507
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
508 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
509
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
510 case '|':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
511 p.addAlternate()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
512 goto ContinueOuterScan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
513
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
514 case ')':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
515 if p.emptyStack() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
516 return nil, p.getErr(ErrUnexpectedParen)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
517 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
518
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
519 if err := p.addGroup(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
520 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
521 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
522 if err := p.popGroup(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
523 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
524 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
525 p.popOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
526
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
527 if p.unit == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
528 goto ContinueOuterScan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
529 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
530
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
531 case '\\':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
532 n, err := p.scanBackslash(false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
533 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
534 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
535 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
536 p.addUnitNode(n)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
537
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
538 case '^':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
539 if p.useOptionM() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
540 p.addUnitType(ntBol)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
541 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
542 p.addUnitType(ntBeginning)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
543 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
544
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
545 case '$':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
546 if p.useOptionM() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
547 p.addUnitType(ntEol)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
548 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
549 p.addUnitType(ntEndZ)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
550 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
551
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
552 case '.':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
553 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
554 p.addUnitSet(ECMAAnyClass())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
555 } else if p.useOptionS() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
556 p.addUnitSet(AnyClass())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
557 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
558 p.addUnitNotone('\n')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
559 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
560
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
561 case '{', '*', '+', '?':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
562 if p.unit == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
563 if wasPrevQuantifier {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
564 return nil, p.getErr(ErrInvalidRepeatOp)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
565 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
566 return nil, p.getErr(ErrMissingRepeatArgument)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
567 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
568 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
569 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
570
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
571 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
572 return nil, p.getErr(ErrInternalError)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
573 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
574
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
575 if err := p.scanBlank(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
576 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
577 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
578
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
579 if p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
580 isQuant = p.isTrueQuantifier()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
581 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
582 if p.charsRight() == 0 || !isQuant {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
583 //maintain odd C# assignment order -- not sure if required, could clean up?
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
584 p.addConcatenate()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
585 goto ContinueOuterScan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
586 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
587
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
588 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
589
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
590 // Handle quantifiers
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
591 for p.unit != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
592 var min, max int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
593 var lazy bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
594
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
595 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
596 case '*':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
597 min = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
598 max = math.MaxInt32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
599
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
600 case '?':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
601 min = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
602 max = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
603
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
604 case '+':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
605 min = 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
606 max = math.MaxInt32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
607
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
608 case '{':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
609 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
610 var err error
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
611 startpos = p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
612 if min, err = p.scanDecimal(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
613 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
614 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
615 max = min
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
616 if startpos < p.textpos() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
617 if p.charsRight() > 0 && p.rightChar(0) == ',' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
618 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
619 if p.charsRight() == 0 || p.rightChar(0) == '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
620 max = math.MaxInt32
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
621 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
622 if max, err = p.scanDecimal(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
623 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
624 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
625 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
626 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
627 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
628
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
629 if startpos == p.textpos() || p.charsRight() == 0 || p.moveRightGetChar() != '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
630 p.addConcatenate()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
631 p.textto(startpos - 1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
632 goto ContinueOuterScan
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
633 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
634 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
635
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
636 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
637 return nil, p.getErr(ErrInternalError)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
638 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
639
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
640 if err := p.scanBlank(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
641 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
642 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
643
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
644 if p.charsRight() == 0 || p.rightChar(0) != '?' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
645 lazy = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
646 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
647 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
648 lazy = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
649 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
650
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
651 if min > max {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
652 return nil, p.getErr(ErrInvalidRepeatSize)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
653 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
654
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
655 p.addConcatenate3(lazy, min, max)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
656 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
657
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
658 ContinueOuterScan:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
659 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
660
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
661 BreakOuterScan:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
662 ;
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
663
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
664 if !p.emptyStack() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
665 return nil, p.getErr(ErrMissingParen)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
666 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
667
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
668 if err := p.addGroup(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
669 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
670 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
671
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
672 return p.unit, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
673
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
674 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
675
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
676 /*
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
677 * Simple parsing for replacement patterns
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
678 */
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
679 func (p *parser) scanReplacement() (*regexNode, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
680 var c, startpos int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
681
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
682 p.concatenation = newRegexNode(ntConcatenate, p.options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
683
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
684 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
685 c = p.charsRight()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
686 if c == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
687 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
688 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
689
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
690 startpos = p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
691
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
692 for c > 0 && p.rightChar(0) != '$' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
693 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
694 c--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
695 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
696
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
697 p.addToConcatenate(startpos, p.textpos()-startpos, true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
698
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
699 if c > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
700 if p.moveRightGetChar() == '$' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
701 n, err := p.scanDollar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
702 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
703 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
704 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
705 p.addUnitNode(n)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
706 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
707 p.addConcatenate()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
708 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
709 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
710
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
711 return p.concatenation, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
712 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
713
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
714 /*
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
715 * Scans $ patterns recognized within replacement patterns
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
716 */
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
717 func (p *parser) scanDollar() (*regexNode, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
718 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
719 return newRegexNodeCh(ntOne, p.options, '$'), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
720 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
721
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
722 ch := p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
723 angled := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
724 backpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
725 lastEndPos := backpos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
726
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
727 // Note angle
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
728
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
729 if ch == '{' && p.charsRight() > 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
730 angled = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
731 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
732 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
733 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
734
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
735 // Try to parse backreference: \1 or \{1} or \{cap}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
736
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
737 if ch >= '0' && ch <= '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
738 if !angled && p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
739 capnum := -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
740 newcapnum := int(ch - '0')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
741 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
742 if p.isCaptureSlot(newcapnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
743 capnum = newcapnum
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
744 lastEndPos = p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
745 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
746
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
747 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
748 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
749 if ch < '0' || ch > '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
750 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
751 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
752 digit := int(ch - '0')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
753 if newcapnum > maxValueDiv10 || (newcapnum == maxValueDiv10 && digit > maxValueMod10) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
754 return nil, p.getErr(ErrCaptureGroupOutOfRange)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
755 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
756
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
757 newcapnum = newcapnum*10 + digit
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
758
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
759 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
760 if p.isCaptureSlot(newcapnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
761 capnum = newcapnum
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
762 lastEndPos = p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
763 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
764 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
765 p.textto(lastEndPos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
766 if capnum >= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
767 return newRegexNodeM(ntRef, p.options, capnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
768 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
769 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
770 capnum, err := p.scanDecimal()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
771 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
772 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
773 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
774 if !angled || p.charsRight() > 0 && p.moveRightGetChar() == '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
775 if p.isCaptureSlot(capnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
776 return newRegexNodeM(ntRef, p.options, capnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
777 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
778 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
779 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
780 } else if angled && IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
781 capname := p.scanCapname()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
782
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
783 if p.charsRight() > 0 && p.moveRightGetChar() == '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
784 if p.isCaptureName(capname) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
785 return newRegexNodeM(ntRef, p.options, p.captureSlotFromName(capname)), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
786 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
787 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
788 } else if !angled {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
789 capnum := 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
790
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
791 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
792 case '$':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
793 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
794 return newRegexNodeCh(ntOne, p.options, '$'), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
795 case '&':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
796 capnum = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
797 case '`':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
798 capnum = replaceLeftPortion
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
799 case '\'':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
800 capnum = replaceRightPortion
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
801 case '+':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
802 capnum = replaceLastGroup
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
803 case '_':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
804 capnum = replaceWholeString
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
805 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
806
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
807 if capnum != 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
808 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
809 return newRegexNodeM(ntRef, p.options, capnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
810 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
811 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
812
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
813 // unrecognized $: literalize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
814
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
815 p.textto(backpos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
816 return newRegexNodeCh(ntOne, p.options, '$'), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
817 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
818
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
819 // scanGroupOpen scans chars following a '(' (not counting the '('), and returns
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
820 // a RegexNode for the type of group scanned, or nil if the group
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
821 // simply changed options (?cimsx-cimsx) or was a comment (#...).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
822 func (p *parser) scanGroupOpen() (*regexNode, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
823 var ch rune
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
824 var nt nodeType
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
825 var err error
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
826 close := '>'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
827 start := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
828
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
829 // just return a RegexNode if we have:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
830 // 1. "(" followed by nothing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
831 // 2. "(x" where x != ?
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
832 // 3. "(?)"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
833 if p.charsRight() == 0 || p.rightChar(0) != '?' || (p.rightChar(0) == '?' && (p.charsRight() > 1 && p.rightChar(1) == ')')) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
834 if p.useOptionN() || p.ignoreNextParen {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
835 p.ignoreNextParen = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
836 return newRegexNode(ntGroup, p.options), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
837 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
838 return newRegexNodeMN(ntCapture, p.options, p.consumeAutocap(), -1), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
839 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
840
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
841 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
842
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
843 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
844 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
845 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
846 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
847
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
848 switch ch = p.moveRightGetChar(); ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
849 case ':':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
850 nt = ntGroup
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
851
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
852 case '=':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
853 p.options &= ^RightToLeft
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
854 nt = ntRequire
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
855
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
856 case '!':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
857 p.options &= ^RightToLeft
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
858 nt = ntPrevent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
859
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
860 case '>':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
861 nt = ntGreedy
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
862
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
863 case '\'':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
864 close = '\''
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
865 fallthrough
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
866
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
867 case '<':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
868 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
869 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
870 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
871
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
872 switch ch = p.moveRightGetChar(); ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
873 case '=':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
874 if close == '\'' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
875 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
876 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
877
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
878 p.options |= RightToLeft
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
879 nt = ntRequire
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
880
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
881 case '!':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
882 if close == '\'' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
883 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
884 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
885
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
886 p.options |= RightToLeft
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
887 nt = ntPrevent
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
888
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
889 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
890 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
891 capnum := -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
892 uncapnum := -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
893 proceed := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
894
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
895 // grab part before -
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
896
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
897 if ch >= '0' && ch <= '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
898 if capnum, err = p.scanDecimal(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
899 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
900 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
901
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
902 if !p.isCaptureSlot(capnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
903 capnum = -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
904 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
905
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
906 // check if we have bogus characters after the number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
907 if p.charsRight() > 0 && !(p.rightChar(0) == close || p.rightChar(0) == '-') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
908 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
909 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
910 if capnum == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
911 return nil, p.getErr(ErrCapNumNotZero)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
912 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
913 } else if IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
914 capname := p.scanCapname()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
915
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
916 if p.isCaptureName(capname) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
917 capnum = p.captureSlotFromName(capname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
918 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
919
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
920 // check if we have bogus character after the name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
921 if p.charsRight() > 0 && !(p.rightChar(0) == close || p.rightChar(0) == '-') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
922 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
923 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
924 } else if ch == '-' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
925 proceed = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
926 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
927 // bad group name - starts with something other than a word character and isn't a number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
928 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
929 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
930
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
931 // grab part after - if any
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
932
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
933 if (capnum != -1 || proceed == true) && p.charsRight() > 0 && p.rightChar(0) == '-' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
934 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
935
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
936 //no more chars left, no closing char, etc
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
937 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
938 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
939 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
940
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
941 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
942 if ch >= '0' && ch <= '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
943 if uncapnum, err = p.scanDecimal(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
944 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
945 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
946
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
947 if !p.isCaptureSlot(uncapnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
948 return nil, p.getErr(ErrUndefinedBackRef, uncapnum)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
949 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
950
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
951 // check if we have bogus characters after the number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
952 if p.charsRight() > 0 && p.rightChar(0) != close {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
953 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
954 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
955 } else if IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
956 uncapname := p.scanCapname()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
957
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
958 if !p.isCaptureName(uncapname) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
959 return nil, p.getErr(ErrUndefinedNameRef, uncapname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
960 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
961 uncapnum = p.captureSlotFromName(uncapname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
962
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
963 // check if we have bogus character after the name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
964 if p.charsRight() > 0 && p.rightChar(0) != close {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
965 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
966 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
967 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
968 // bad group name - starts with something other than a word character and isn't a number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
969 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
970 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
971 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
972
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
973 // actually make the node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
974
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
975 if (capnum != -1 || uncapnum != -1) && p.charsRight() > 0 && p.moveRightGetChar() == close {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
976 return newRegexNodeMN(ntCapture, p.options, capnum, uncapnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
977 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
978 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
979 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
980
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
981 case '(':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
982 // alternation construct (?(...) | )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
983
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
984 parenPos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
985 if p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
986 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
987
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
988 // check if the alternation condition is a backref
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
989 if ch >= '0' && ch <= '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
990 var capnum int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
991 if capnum, err = p.scanDecimal(); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
992 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
993 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
994 if p.charsRight() > 0 && p.moveRightGetChar() == ')' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
995 if p.isCaptureSlot(capnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
996 return newRegexNodeM(ntTestref, p.options, capnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
997 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
998 return nil, p.getErr(ErrUndefinedReference, capnum)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
999 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1000
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1001 return nil, p.getErr(ErrMalformedReference, capnum)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1002
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1003 } else if IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1004 capname := p.scanCapname()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1005
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1006 if p.isCaptureName(capname) && p.charsRight() > 0 && p.moveRightGetChar() == ')' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1007 return newRegexNodeM(ntTestref, p.options, p.captureSlotFromName(capname)), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1008 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1009 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1010 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1011 // not a backref
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1012 nt = ntTestgroup
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1013 p.textto(parenPos - 1) // jump to the start of the parentheses
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1014 p.ignoreNextParen = true // but make sure we don't try to capture the insides
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1015
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1016 charsRight := p.charsRight()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1017 if charsRight >= 3 && p.rightChar(1) == '?' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1018 rightchar2 := p.rightChar(2)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1019 // disallow comments in the condition
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1020 if rightchar2 == '#' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1021 return nil, p.getErr(ErrAlternationCantHaveComment)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1022 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1023
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1024 // disallow named capture group (?<..>..) in the condition
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1025 if rightchar2 == '\'' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1026 return nil, p.getErr(ErrAlternationCantCapture)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1027 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1028
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1029 if charsRight >= 4 && (rightchar2 == '<' && p.rightChar(3) != '!' && p.rightChar(3) != '=') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1030 return nil, p.getErr(ErrAlternationCantCapture)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1031 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1032 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1033
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1034 case 'P':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1035 if p.useRE2() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1036 // support for P<name> syntax
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1037 if p.charsRight() < 3 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1038 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1039 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1040
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1041 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1042 if ch != '<' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1043 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1044 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1045
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1046 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1047 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1048
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1049 if IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1050 capnum := -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1051 capname := p.scanCapname()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1052
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1053 if p.isCaptureName(capname) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1054 capnum = p.captureSlotFromName(capname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1055 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1056
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1057 // check if we have bogus character after the name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1058 if p.charsRight() > 0 && p.rightChar(0) != '>' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1059 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1060 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1061
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1062 // actually make the node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1063
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1064 if capnum != -1 && p.charsRight() > 0 && p.moveRightGetChar() == '>' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1065 return newRegexNodeMN(ntCapture, p.options, capnum, -1), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1066 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1067 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1068
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1069 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1070 // bad group name - starts with something other than a word character and isn't a number
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1071 return nil, p.getErr(ErrInvalidGroupName)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1072 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1073 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1074 // if we're not using RE2 compat mode then
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1075 // we just behave like normal
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1076 fallthrough
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1077
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1078 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1079 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1080
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1081 nt = ntGroup
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1082 // disallow options in the children of a testgroup node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1083 if p.group.t != ntTestgroup {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1084 p.scanOptions()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1085 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1086 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1087 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1088 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1089
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1090 if ch = p.moveRightGetChar(); ch == ')' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1091 return nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1092 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1093
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1094 if ch != ':' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1095 goto BreakRecognize
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1096 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1097
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1098 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1099
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1100 return newRegexNode(nt, p.options), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1101 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1102
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1103 BreakRecognize:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1104
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1105 // break Recognize comes here
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1106
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1107 return nil, p.getErr(ErrUnrecognizedGrouping, string(p.pattern[start:p.textpos()]))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1108 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1109
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1110 // scans backslash specials and basics
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1111 func (p *parser) scanBackslash(scanOnly bool) (*regexNode, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1112
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1113 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1114 return nil, p.getErr(ErrIllegalEndEscape)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1115 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1116
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1117 switch ch := p.rightChar(0); ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1118 case 'b', 'B', 'A', 'G', 'Z', 'z':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1119 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1120 return newRegexNode(p.typeFromCode(ch), p.options), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1121
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1122 case 'w':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1123 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1124 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1125 return newRegexNodeSet(ntSet, p.options, ECMAWordClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1126 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1127 return newRegexNodeSet(ntSet, p.options, WordClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1128
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1129 case 'W':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1130 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1131 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1132 return newRegexNodeSet(ntSet, p.options, NotECMAWordClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1133 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1134 return newRegexNodeSet(ntSet, p.options, NotWordClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1135
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1136 case 's':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1137 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1138 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1139 return newRegexNodeSet(ntSet, p.options, ECMASpaceClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1140 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1141 return newRegexNodeSet(ntSet, p.options, SpaceClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1142
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1143 case 'S':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1144 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1145 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1146 return newRegexNodeSet(ntSet, p.options, NotECMASpaceClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1147 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1148 return newRegexNodeSet(ntSet, p.options, NotSpaceClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1149
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1150 case 'd':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1151 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1152 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1153 return newRegexNodeSet(ntSet, p.options, ECMADigitClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1154 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1155 return newRegexNodeSet(ntSet, p.options, DigitClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1156
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1157 case 'D':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1158 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1159 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1160 return newRegexNodeSet(ntSet, p.options, NotECMADigitClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1161 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1162 return newRegexNodeSet(ntSet, p.options, NotDigitClass()), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1163
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1164 case 'p', 'P':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1165 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1166 prop, err := p.parseProperty()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1167 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1168 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1169 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1170 cc := &CharSet{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1171 cc.addCategory(prop, (ch != 'p'), p.useOptionI(), p.patternRaw)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1172 if p.useOptionI() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1173 cc.addLowercase()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1174 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1175
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1176 return newRegexNodeSet(ntSet, p.options, cc), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1177
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1178 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1179 return p.scanBasicBackslash(scanOnly)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1180 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1181 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1182
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1183 // Scans \-style backreferences and character escapes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1184 func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1185 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1186 return nil, p.getErr(ErrIllegalEndEscape)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1187 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1188 angled := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1189 close := '\x00'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1190
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1191 backpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1192 ch := p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1193
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1194 // allow \k<foo> instead of \<foo>, which is now deprecated
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1195
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1196 if ch == 'k' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1197 if p.charsRight() >= 2 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1198 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1199 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1200
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1201 if ch == '<' || ch == '\'' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1202 angled = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1203 if ch == '\'' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1204 close = '\''
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1205 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1206 close = '>'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1207 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1208 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1209 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1210
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1211 if !angled || p.charsRight() <= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1212 return nil, p.getErr(ErrMalformedNameRef)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1213 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1214
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1215 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1216
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1217 } else if (ch == '<' || ch == '\'') && p.charsRight() > 1 { // Note angle without \g
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1218 angled = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1219 if ch == '\'' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1220 close = '\''
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1221 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1222 close = '>'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1223 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1224
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1225 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1226 ch = p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1227 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1228
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1229 // Try to parse backreference: \<1> or \<cap>
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1230
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1231 if angled && ch >= '0' && ch <= '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1232 capnum, err := p.scanDecimal()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1233 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1234 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1235 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1236
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1237 if p.charsRight() > 0 && p.moveRightGetChar() == close {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1238 if p.isCaptureSlot(capnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1239 return newRegexNodeM(ntRef, p.options, capnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1240 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1241 return nil, p.getErr(ErrUndefinedBackRef, capnum)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1242 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1243 } else if !angled && ch >= '1' && ch <= '9' { // Try to parse backreference or octal: \1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1244 capnum, err := p.scanDecimal()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1245 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1246 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1247 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1248
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1249 if scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1250 return nil, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1251 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1252
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1253 if p.isCaptureSlot(capnum) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1254 return newRegexNodeM(ntRef, p.options, capnum), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1255 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1256 if capnum <= 9 && !p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1257 return nil, p.getErr(ErrUndefinedBackRef, capnum)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1258 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1259
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1260 } else if angled && IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1261 capname := p.scanCapname()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1262
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1263 if p.charsRight() > 0 && p.moveRightGetChar() == close {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1264 if p.isCaptureName(capname) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1265 return newRegexNodeM(ntRef, p.options, p.captureSlotFromName(capname)), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1266 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1267 return nil, p.getErr(ErrUndefinedNameRef, capname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1268 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1269 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1270
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1271 // Not backreference: must be char code
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1272
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1273 p.textto(backpos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1274 ch, err := p.scanCharEscape()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1275 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1276 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1277 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1278
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1279 if p.useOptionI() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1280 ch = unicode.ToLower(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1281 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1282
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1283 return newRegexNodeCh(ntOne, p.options, ch), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1284 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1285
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1286 // Scans X for \p{X} or \P{X}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1287 func (p *parser) parseProperty() (string, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1288 if p.charsRight() < 3 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1289 return "", p.getErr(ErrIncompleteSlashP)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1290 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1291 ch := p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1292 if ch != '{' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1293 return "", p.getErr(ErrMalformedSlashP)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1294 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1295
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1296 startpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1297 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1298 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1299 if !(IsWordChar(ch) || ch == '-') {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1300 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1301 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1302 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1303 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1304 capname := string(p.pattern[startpos:p.textpos()])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1305
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1306 if p.charsRight() == 0 || p.moveRightGetChar() != '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1307 return "", p.getErr(ErrIncompleteSlashP)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1308 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1309
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1310 if !isValidUnicodeCat(capname) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1311 return "", p.getErr(ErrUnknownSlashP, capname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1312 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1313
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1314 return capname, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1315 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1316
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1317 // Returns ReNode type for zero-length assertions with a \ code.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1318 func (p *parser) typeFromCode(ch rune) nodeType {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1319 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1320 case 'b':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1321 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1322 return ntECMABoundary
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1323 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1324 return ntBoundary
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1325 case 'B':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1326 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1327 return ntNonECMABoundary
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1328 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1329 return ntNonboundary
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1330 case 'A':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1331 return ntBeginning
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1332 case 'G':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1333 return ntStart
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1334 case 'Z':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1335 return ntEndZ
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1336 case 'z':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1337 return ntEnd
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1338 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1339 return ntNothing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1340 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1341 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1342
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1343 // Scans whitespace or x-mode comments.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1344 func (p *parser) scanBlank() error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1345 if p.useOptionX() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1346 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1347 for p.charsRight() > 0 && isSpace(p.rightChar(0)) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1348 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1349 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1350
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1351 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1352 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1353 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1354
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1355 if p.rightChar(0) == '#' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1356 for p.charsRight() > 0 && p.rightChar(0) != '\n' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1357 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1358 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1359 } else if p.charsRight() >= 3 && p.rightChar(2) == '#' &&
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1360 p.rightChar(1) == '?' && p.rightChar(0) == '(' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1361 for p.charsRight() > 0 && p.rightChar(0) != ')' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1362 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1363 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1364 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1365 return p.getErr(ErrUnterminatedComment)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1366 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1367 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1368 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1369 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1370 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1371 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1372 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1373 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1374 if p.charsRight() < 3 || p.rightChar(2) != '#' ||
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1375 p.rightChar(1) != '?' || p.rightChar(0) != '(' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1376 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1377 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1378
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1379 for p.charsRight() > 0 && p.rightChar(0) != ')' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1380 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1381 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1382 if p.charsRight() == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1383 return p.getErr(ErrUnterminatedComment)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1384 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1385 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1386 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1387 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1388 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1389 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1390
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1391 func (p *parser) scanCapname() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1392 startpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1393
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1394 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1395 if !IsWordChar(p.moveRightGetChar()) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1396 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1397 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1398 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1399 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1400
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1401 return string(p.pattern[startpos:p.textpos()])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1402 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1403
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1404 //Scans contents of [] (not including []'s), and converts to a set.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1405 func (p *parser) scanCharSet(caseInsensitive, scanOnly bool) (*CharSet, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1406 ch := '\x00'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1407 chPrev := '\x00'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1408 inRange := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1409 firstChar := true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1410 closed := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1411
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1412 var cc *CharSet
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1413 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1414 cc = &CharSet{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1415 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1416
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1417 if p.charsRight() > 0 && p.rightChar(0) == '^' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1418 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1419 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1420 cc.negate = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1421 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1422 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1423
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1424 for ; p.charsRight() > 0; firstChar = false {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1425 fTranslatedChar := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1426 ch = p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1427 if ch == ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1428 if !firstChar {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1429 closed = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1430 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1431 } else if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1432 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1433 cc.addRanges(NoneClass().ranges)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1434 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1435 closed = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1436 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1437 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1438
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1439 } else if ch == '\\' && p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1440 switch ch = p.moveRightGetChar(); ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1441 case 'D', 'd':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1442 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1443 if inRange {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1444 return nil, p.getErr(ErrBadClassInCharRange, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1445 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1446 cc.addDigit(p.useOptionE(), ch == 'D', p.patternRaw)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1447 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1448 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1449
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1450 case 'S', 's':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1451 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1452 if inRange {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1453 return nil, p.getErr(ErrBadClassInCharRange, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1454 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1455 cc.addSpace(p.useOptionE(), ch == 'S')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1456 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1457 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1458
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1459 case 'W', 'w':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1460 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1461 if inRange {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1462 return nil, p.getErr(ErrBadClassInCharRange, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1463 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1464
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1465 cc.addWord(p.useOptionE(), ch == 'W')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1466 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1467 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1468
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1469 case 'p', 'P':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1470 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1471 if inRange {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1472 return nil, p.getErr(ErrBadClassInCharRange, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1473 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1474 prop, err := p.parseProperty()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1475 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1476 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1477 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1478 cc.addCategory(prop, (ch != 'p'), caseInsensitive, p.patternRaw)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1479 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1480 p.parseProperty()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1481 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1482
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1483 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1484
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1485 case '-':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1486 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1487 cc.addRange(ch, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1488 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1489 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1490
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1491 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1492 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1493 var err error
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1494 ch, err = p.scanCharEscape() // non-literal character
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1495 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1496 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1497 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1498 fTranslatedChar = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1499 break // this break will only break out of the switch
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1500 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1501 } else if ch == '[' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1502 // This is code for Posix style properties - [:Ll:] or [:IsTibetan:].
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1503 // It currently doesn't do anything other than skip the whole thing!
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1504 if p.charsRight() > 0 && p.rightChar(0) == ':' && !inRange {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1505 savePos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1506
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1507 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1508 negate := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1509 if p.charsRight() > 1 && p.rightChar(0) == '^' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1510 negate = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1511 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1512 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1513
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1514 nm := p.scanCapname() // snag the name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1515 if !scanOnly && p.useRE2() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1516 // look up the name since these are valid for RE2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1517 // add the group based on the name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1518 if ok := cc.addNamedASCII(nm, negate); !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1519 return nil, p.getErr(ErrInvalidCharRange)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1520 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1521 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1522 if p.charsRight() < 2 || p.moveRightGetChar() != ':' || p.moveRightGetChar() != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1523 p.textto(savePos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1524 } else if p.useRE2() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1525 // move on
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1526 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1527 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1528 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1529 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1530
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1531 if inRange {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1532 inRange = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1533 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1534 if ch == '[' && !fTranslatedChar && !firstChar {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1535 // We thought we were in a range, but we're actually starting a subtraction.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1536 // In that case, we'll add chPrev to our char class, skip the opening [, and
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1537 // scan the new character class recursively.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1538 cc.addChar(chPrev)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1539 sub, err := p.scanCharSet(caseInsensitive, false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1540 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1541 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1542 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1543 cc.addSubtraction(sub)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1544
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1545 if p.charsRight() > 0 && p.rightChar(0) != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1546 return nil, p.getErr(ErrSubtractionMustBeLast)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1547 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1548 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1549 // a regular range, like a-z
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1550 if chPrev > ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1551 return nil, p.getErr(ErrReversedCharRange)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1552 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1553 cc.addRange(chPrev, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1554 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1555 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1556 } else if p.charsRight() >= 2 && p.rightChar(0) == '-' && p.rightChar(1) != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1557 // this could be the start of a range
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1558 chPrev = ch
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1559 inRange = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1560 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1561 } else if p.charsRight() >= 1 && ch == '-' && !fTranslatedChar && p.rightChar(0) == '[' && !firstChar {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1562 // we aren't in a range, and now there is a subtraction. Usually this happens
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1563 // only when a subtraction follows a range, like [a-z-[b]]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1564 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1565 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1566 sub, err := p.scanCharSet(caseInsensitive, false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1567 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1568 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1569 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1570 cc.addSubtraction(sub)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1571
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1572 if p.charsRight() > 0 && p.rightChar(0) != ']' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1573 return nil, p.getErr(ErrSubtractionMustBeLast)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1574 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1575 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1576 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1577 p.scanCharSet(caseInsensitive, true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1578 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1579 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1580 if !scanOnly {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1581 cc.addRange(ch, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1582 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1583 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1584 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1585
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1586 if !closed {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1587 return nil, p.getErr(ErrUnterminatedBracket)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1588 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1589
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1590 if !scanOnly && caseInsensitive {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1591 cc.addLowercase()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1592 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1593
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1594 return cc, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1595 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1596
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1597 // Scans any number of decimal digits (pegs value at 2^31-1 if too large)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1598 func (p *parser) scanDecimal() (int, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1599 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1600 var d int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1601
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1602 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1603 d = int(p.rightChar(0) - '0')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1604 if d < 0 || d > 9 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1605 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1606 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1607 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1608
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1609 if i > maxValueDiv10 || (i == maxValueDiv10 && d > maxValueMod10) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1610 return 0, p.getErr(ErrCaptureGroupOutOfRange)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1611 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1612
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1613 i *= 10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1614 i += d
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1615 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1616
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1617 return int(i), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1618 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1619
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1620 // Returns true for options allowed only at the top level
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1621 func isOnlyTopOption(option RegexOptions) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1622 return option == RightToLeft || option == ECMAScript || option == RE2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1623 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1624
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1625 // Scans cimsx-cimsx option string, stops at the first unrecognized char.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1626 func (p *parser) scanOptions() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1627
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1628 for off := false; p.charsRight() > 0; p.moveRight(1) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1629 ch := p.rightChar(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1630
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1631 if ch == '-' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1632 off = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1633 } else if ch == '+' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1634 off = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1635 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1636 option := optionFromCode(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1637 if option == 0 || isOnlyTopOption(option) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1638 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1639 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1640
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1641 if off {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1642 p.options &= ^option
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1643 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1644 p.options |= option
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1645 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1646 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1647 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1648 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1649
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1650 // Scans \ code for escape codes that map to single unicode chars.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1651 func (p *parser) scanCharEscape() (r rune, err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1652
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1653 ch := p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1654
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1655 if ch >= '0' && ch <= '7' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1656 p.moveLeft()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1657 return p.scanOctal(), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1658 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1659
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1660 pos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1661
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1662 switch ch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1663 case 'x':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1664 // support for \x{HEX} syntax from Perl and PCRE
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1665 if p.charsRight() > 0 && p.rightChar(0) == '{' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1666 if p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1667 return ch, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1668 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1669 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1670 return p.scanHexUntilBrace()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1671 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1672 r, err = p.scanHex(2)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1673 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1674 case 'u':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1675 r, err = p.scanHex(4)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1676 case 'a':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1677 return '\u0007', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1678 case 'b':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1679 return '\b', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1680 case 'e':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1681 return '\u001B', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1682 case 'f':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1683 return '\f', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1684 case 'n':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1685 return '\n', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1686 case 'r':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1687 return '\r', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1688 case 't':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1689 return '\t', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1690 case 'v':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1691 return '\u000B', nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1692 case 'c':
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1693 r, err = p.scanControl()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1694 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1695 if !p.useOptionE() && IsWordChar(ch) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1696 return 0, p.getErr(ErrUnrecognizedEscape, string(ch))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1697 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1698 return ch, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1699 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1700 if err != nil && p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1701 p.textto(pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1702 return ch, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1703 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1704 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1705 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1706
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1707 // Grabs and converts an ascii control character
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1708 func (p *parser) scanControl() (rune, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1709 if p.charsRight() <= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1710 return 0, p.getErr(ErrMissingControl)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1711 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1712
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1713 ch := p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1714
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1715 // \ca interpreted as \cA
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1716
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1717 if ch >= 'a' && ch <= 'z' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1718 ch = (ch - ('a' - 'A'))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1719 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1720 ch = (ch - '@')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1721 if ch >= 0 && ch < ' ' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1722 return ch, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1723 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1724
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1725 return 0, p.getErr(ErrUnrecognizedControl)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1726
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1727 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1728
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1729 // Scan hex digits until we hit a closing brace.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1730 // Non-hex digits, hex value too large for UTF-8, or running out of chars are errors
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1731 func (p *parser) scanHexUntilBrace() (rune, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1732 // PCRE spec reads like unlimited hex digits are allowed, but unicode has a limit
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1733 // so we can enforce that
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1734 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1735 hasContent := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1736
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1737 for p.charsRight() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1738 ch := p.moveRightGetChar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1739 if ch == '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1740 // hit our close brace, we're done here
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1741 // prevent \x{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1742 if !hasContent {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1743 return 0, p.getErr(ErrTooFewHex)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1744 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1745 return rune(i), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1746 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1747 hasContent = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1748 // no brace needs to be hex digit
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1749 d := hexDigit(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1750 if d < 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1751 return 0, p.getErr(ErrMissingBrace)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1752 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1753
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1754 i *= 0x10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1755 i += d
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1756
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1757 if i > unicode.MaxRune {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1758 return 0, p.getErr(ErrInvalidHex)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1759 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1760 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1761
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1762 // we only make it here if we run out of digits without finding the brace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1763 return 0, p.getErr(ErrMissingBrace)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1764 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1765
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1766 // Scans exactly c hex digits (c=2 for \xFF, c=4 for \uFFFF)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1767 func (p *parser) scanHex(c int) (rune, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1768
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1769 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1770
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1771 if p.charsRight() >= c {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1772 for c > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1773 d := hexDigit(p.moveRightGetChar())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1774 if d < 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1775 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1776 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1777 i *= 0x10
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1778 i += d
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1779 c--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1780 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1781 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1782
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1783 if c > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1784 return 0, p.getErr(ErrTooFewHex)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1785 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1786
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1787 return rune(i), nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1788 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1789
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1790 // Returns n <= 0xF for a hex digit.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1791 func hexDigit(ch rune) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1792
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1793 if d := uint(ch - '0'); d <= 9 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1794 return int(d)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1795 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1796
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1797 if d := uint(ch - 'a'); d <= 5 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1798 return int(d + 0xa)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1799 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1800
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1801 if d := uint(ch - 'A'); d <= 5 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1802 return int(d + 0xa)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1803 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1804
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1805 return -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1806 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1807
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1808 // Scans up to three octal digits (stops before exceeding 0377).
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1809 func (p *parser) scanOctal() rune {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1810 // Consume octal chars only up to 3 digits and value 0377
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1811
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1812 c := 3
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1813
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1814 if c > p.charsRight() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1815 c = p.charsRight()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1816 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1817
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1818 //we know the first char is good because the caller had to check
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1819 i := 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1820 d := int(p.rightChar(0) - '0')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1821 for c > 0 && d <= 7 && d >= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1822 if i >= 0x20 && p.useOptionE() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1823 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1824 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1825 i *= 8
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1826 i += d
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1827 c--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1828
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1829 p.moveRight(1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1830 if !p.rightMost() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1831 d = int(p.rightChar(0) - '0')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1832 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1833 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1834
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1835 // Octal codes only go up to 255. Any larger and the behavior that Perl follows
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1836 // is simply to truncate the high bits.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1837 i &= 0xFF
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1838
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1839 return rune(i)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1840 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1841
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1842 // Returns the current parsing position.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1843 func (p *parser) textpos() int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1844 return p.currentPos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1845 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1846
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1847 // Zaps to a specific parsing position.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1848 func (p *parser) textto(pos int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1849 p.currentPos = pos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1850 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1851
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1852 // Returns the char at the right of the current parsing position and advances to the right.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1853 func (p *parser) moveRightGetChar() rune {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1854 ch := p.pattern[p.currentPos]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1855 p.currentPos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1856 return ch
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1857 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1858
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1859 // Moves the current position to the right.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1860 func (p *parser) moveRight(i int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1861 // default would be 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1862 p.currentPos += i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1863 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1864
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1865 // Moves the current parsing position one to the left.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1866 func (p *parser) moveLeft() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1867 p.currentPos--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1868 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1869
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1870 // Returns the char left of the current parsing position.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1871 func (p *parser) charAt(i int) rune {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1872 return p.pattern[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1873 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1874
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1875 // Returns the char i chars right of the current parsing position.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1876 func (p *parser) rightChar(i int) rune {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1877 // default would be 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1878 return p.pattern[p.currentPos+i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1879 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1880
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1881 // Number of characters to the right of the current parsing position.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1882 func (p *parser) charsRight() int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1883 return len(p.pattern) - p.currentPos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1884 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1885
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1886 func (p *parser) rightMost() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1887 return p.currentPos == len(p.pattern)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1888 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1889
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1890 // Looks up the slot number for a given name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1891 func (p *parser) captureSlotFromName(capname string) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1892 return p.capnames[capname]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1893 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1894
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1895 // True if the capture slot was noted
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1896 func (p *parser) isCaptureSlot(i int) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1897 if p.caps != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1898 _, ok := p.caps[i]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1899 return ok
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1900 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1901
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1902 return (i >= 0 && i < p.capsize)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1903 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1904
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1905 // Looks up the slot number for a given name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1906 func (p *parser) isCaptureName(capname string) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1907 if p.capnames == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1908 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1909 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1910
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1911 _, ok := p.capnames[capname]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1912 return ok
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1913 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1914
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1915 // option shortcuts
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1916
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1917 // True if N option disabling '(' autocapture is on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1918 func (p *parser) useOptionN() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1919 return (p.options & ExplicitCapture) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1920 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1921
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1922 // True if I option enabling case-insensitivity is on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1923 func (p *parser) useOptionI() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1924 return (p.options & IgnoreCase) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1925 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1926
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1927 // True if M option altering meaning of $ and ^ is on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1928 func (p *parser) useOptionM() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1929 return (p.options & Multiline) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1930 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1931
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1932 // True if S option altering meaning of . is on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1933 func (p *parser) useOptionS() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1934 return (p.options & Singleline) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1935 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1936
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1937 // True if X option enabling whitespace/comment mode is on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1938 func (p *parser) useOptionX() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1939 return (p.options & IgnorePatternWhitespace) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1940 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1941
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1942 // True if E option enabling ECMAScript behavior on.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1943 func (p *parser) useOptionE() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1944 return (p.options & ECMAScript) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1945 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1946
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1947 // true to use RE2 compatibility parsing behavior.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1948 func (p *parser) useRE2() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1949 return (p.options & RE2) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1950 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1951
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1952 // True if options stack is empty.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1953 func (p *parser) emptyOptionsStack() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1954 return len(p.optionsStack) == 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1955 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1956
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1957 // Finish the current quantifiable (when a quantifier is not found or is not possible)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1958 func (p *parser) addConcatenate() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1959 // The first (| inside a Testgroup group goes directly to the group
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1960 p.concatenation.addChild(p.unit)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1961 p.unit = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1962 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1963
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1964 // Finish the current quantifiable (when a quantifier is found)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1965 func (p *parser) addConcatenate3(lazy bool, min, max int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1966 p.concatenation.addChild(p.unit.makeQuantifier(lazy, min, max))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1967 p.unit = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1968 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1969
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1970 // Sets the current unit to a single char node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1971 func (p *parser) addUnitOne(ch rune) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1972 if p.useOptionI() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1973 ch = unicode.ToLower(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1974 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1975
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1976 p.unit = newRegexNodeCh(ntOne, p.options, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1977 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1978
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1979 // Sets the current unit to a single inverse-char node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1980 func (p *parser) addUnitNotone(ch rune) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1981 if p.useOptionI() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1982 ch = unicode.ToLower(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1983 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1984
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1985 p.unit = newRegexNodeCh(ntNotone, p.options, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1986 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1987
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1988 // Sets the current unit to a single set node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1989 func (p *parser) addUnitSet(set *CharSet) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1990 p.unit = newRegexNodeSet(ntSet, p.options, set)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1991 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1992
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1993 // Sets the current unit to a subtree
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1994 func (p *parser) addUnitNode(node *regexNode) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1995 p.unit = node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1996 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1997
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1998 // Sets the current unit to an assertion of the specified type
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1999 func (p *parser) addUnitType(t nodeType) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2000 p.unit = newRegexNode(t, p.options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2001 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2002
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2003 // Finish the current group (in response to a ')' or end)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2004 func (p *parser) addGroup() error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2005 if p.group.t == ntTestgroup || p.group.t == ntTestref {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2006 p.group.addChild(p.concatenation.reverseLeft())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2007 if (p.group.t == ntTestref && len(p.group.children) > 2) || len(p.group.children) > 3 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2008 return p.getErr(ErrTooManyAlternates)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2009 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2010 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2011 p.alternation.addChild(p.concatenation.reverseLeft())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2012 p.group.addChild(p.alternation)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2013 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2014
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2015 p.unit = p.group
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2016 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2017 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2018
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2019 // Pops the option stack, but keeps the current options unchanged.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2020 func (p *parser) popKeepOptions() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2021 lastIdx := len(p.optionsStack) - 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2022 p.optionsStack = p.optionsStack[:lastIdx]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2023 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2024
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2025 // Recalls options from the stack.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2026 func (p *parser) popOptions() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2027 lastIdx := len(p.optionsStack) - 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2028 // get the last item on the stack and then remove it by reslicing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2029 p.options = p.optionsStack[lastIdx]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2030 p.optionsStack = p.optionsStack[:lastIdx]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2031 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2032
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2033 // Saves options on a stack.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2034 func (p *parser) pushOptions() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2035 p.optionsStack = append(p.optionsStack, p.options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2036 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2037
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2038 // Add a string to the last concatenate.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2039 func (p *parser) addToConcatenate(pos, cch int, isReplacement bool) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2040 var node *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2041
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2042 if cch == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2043 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2044 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2045
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2046 if cch > 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2047 str := p.pattern[pos : pos+cch]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2048
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2049 if p.useOptionI() && !isReplacement {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2050 // We do the ToLower character by character for consistency. With surrogate chars, doing
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2051 // a ToLower on the entire string could actually change the surrogate pair. This is more correct
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2052 // linguistically, but since Regex doesn't support surrogates, it's more important to be
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2053 // consistent.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2054 for i := 0; i < len(str); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2055 str[i] = unicode.ToLower(str[i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2056 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2057 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2058
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2059 node = newRegexNodeStr(ntMulti, p.options, str)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2060 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2061 ch := p.charAt(pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2062
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2063 if p.useOptionI() && !isReplacement {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2064 ch = unicode.ToLower(ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2065 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2066
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2067 node = newRegexNodeCh(ntOne, p.options, ch)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2068 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2069
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2070 p.concatenation.addChild(node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2071 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2072
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2073 // Push the parser state (in response to an open paren)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2074 func (p *parser) pushGroup() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2075 p.group.next = p.stack
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2076 p.alternation.next = p.group
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2077 p.concatenation.next = p.alternation
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2078 p.stack = p.concatenation
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2079 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2080
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2081 // Remember the pushed state (in response to a ')')
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2082 func (p *parser) popGroup() error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2083 p.concatenation = p.stack
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2084 p.alternation = p.concatenation.next
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2085 p.group = p.alternation.next
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2086 p.stack = p.group.next
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2087
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2088 // The first () inside a Testgroup group goes directly to the group
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2089 if p.group.t == ntTestgroup && len(p.group.children) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2090 if p.unit == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2091 return p.getErr(ErrConditionalExpression)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2092 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2093
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2094 p.group.addChild(p.unit)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2095 p.unit = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2096 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2097 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2098 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2099
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2100 // True if the group stack is empty.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2101 func (p *parser) emptyStack() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2102 return p.stack == nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2103 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2104
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2105 // Start a new round for the parser state (in response to an open paren or string start)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2106 func (p *parser) startGroup(openGroup *regexNode) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2107 p.group = openGroup
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2108 p.alternation = newRegexNode(ntAlternate, p.options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2109 p.concatenation = newRegexNode(ntConcatenate, p.options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2110 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2111
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2112 // Finish the current concatenation (in response to a |)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2113 func (p *parser) addAlternate() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2114 // The | parts inside a Testgroup group go directly to the group
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2115
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2116 if p.group.t == ntTestgroup || p.group.t == ntTestref {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2117 p.group.addChild(p.concatenation.reverseLeft())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2118 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2119 p.alternation.addChild(p.concatenation.reverseLeft())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2120 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2121
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2122 p.concatenation = newRegexNode(ntConcatenate, p.options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2123 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2124
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2125 // For categorizing ascii characters.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2126
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2127 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2128 Q byte = 5 // quantifier
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2129 S = 4 // ordinary stopper
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2130 Z = 3 // ScanBlank stopper
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2131 X = 2 // whitespace
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2132 E = 1 // should be escaped
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2133 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2134
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2135 var _category = []byte{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2136 //01 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2137 0, 0, 0, 0, 0, 0, 0, 0, 0, X, X, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2138 // ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2139 X, 0, 0, Z, S, 0, 0, 0, S, S, Q, Q, 0, 0, S, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Q,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2140 //@A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2141 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, S, 0,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2142 //'a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2143 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Q, S, 0, 0, 0,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2144 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2145
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2146 func isSpace(ch rune) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2147 return (ch <= ' ' && _category[ch] == X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2148 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2149
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2150 // Returns true for those characters that terminate a string of ordinary chars.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2151 func isSpecial(ch rune) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2152 return (ch <= '|' && _category[ch] >= S)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2153 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2154
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2155 // Returns true for those characters that terminate a string of ordinary chars.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2156 func isStopperX(ch rune) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2157 return (ch <= '|' && _category[ch] >= X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2158 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2159
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2160 // Returns true for those characters that begin a quantifier.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2161 func isQuantifier(ch rune) bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2162 return (ch <= '{' && _category[ch] >= Q)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2163 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2164
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2165 func (p *parser) isTrueQuantifier() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2166 nChars := p.charsRight()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2167 if nChars == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2168 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2169 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2170
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2171 startpos := p.textpos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2172 ch := p.charAt(startpos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2173 if ch != '{' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2174 return ch <= '{' && _category[ch] >= Q
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2175 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2176
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2177 //UGLY: this is ugly -- the original code was ugly too
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2178 pos := startpos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2179 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2180 nChars--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2181 if nChars <= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2182 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2183 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2184 pos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2185 ch = p.charAt(pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2186 if ch < '0' || ch > '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2187 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2188 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2189 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2190
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2191 if nChars == 0 || pos-startpos == 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2192 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2193 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2194 if ch == '}' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2195 return true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2196 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2197 if ch != ',' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2198 return false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2199 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2200 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2201 nChars--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2202 if nChars <= 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2203 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2204 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2205 pos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2206 ch = p.charAt(pos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2207 if ch < '0' || ch > '9' {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2208 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2209 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2210 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2211
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2212 return nChars > 0 && ch == '}'
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2213 }