parser.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. // Package cascadia is an implementation of CSS selectors.
  2. package cascadia
  3. import (
  4. "errors"
  5. "fmt"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. )
  10. // a parser for CSS selectors
  11. type parser struct {
  12. s string // the source text
  13. i int // the current position
  14. // if `false`, parsing a pseudo-element
  15. // returns an error.
  16. acceptPseudoElements bool
  17. }
  18. // parseEscape parses a backslash escape.
  19. func (p *parser) parseEscape() (result string, err error) {
  20. if len(p.s) < p.i+2 || p.s[p.i] != '\\' {
  21. return "", errors.New("invalid escape sequence")
  22. }
  23. start := p.i + 1
  24. c := p.s[start]
  25. switch {
  26. case c == '\r' || c == '\n' || c == '\f':
  27. return "", errors.New("escaped line ending outside string")
  28. case hexDigit(c):
  29. // unicode escape (hex)
  30. var i int
  31. for i = start; i < start+6 && i < len(p.s) && hexDigit(p.s[i]); i++ {
  32. // empty
  33. }
  34. v, _ := strconv.ParseUint(p.s[start:i], 16, 64)
  35. if len(p.s) > i {
  36. switch p.s[i] {
  37. case '\r':
  38. i++
  39. if len(p.s) > i && p.s[i] == '\n' {
  40. i++
  41. }
  42. case ' ', '\t', '\n', '\f':
  43. i++
  44. }
  45. }
  46. p.i = i
  47. return string(rune(v)), nil
  48. }
  49. // Return the literal character after the backslash.
  50. result = p.s[start : start+1]
  51. p.i += 2
  52. return result, nil
  53. }
  54. // toLowerASCII returns s with all ASCII capital letters lowercased.
  55. func toLowerASCII(s string) string {
  56. var b []byte
  57. for i := 0; i < len(s); i++ {
  58. if c := s[i]; 'A' <= c && c <= 'Z' {
  59. if b == nil {
  60. b = make([]byte, len(s))
  61. copy(b, s)
  62. }
  63. b[i] = s[i] + ('a' - 'A')
  64. }
  65. }
  66. if b == nil {
  67. return s
  68. }
  69. return string(b)
  70. }
  71. func hexDigit(c byte) bool {
  72. return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
  73. }
  74. // nameStart returns whether c can be the first character of an identifier
  75. // (not counting an initial hyphen, or an escape sequence).
  76. func nameStart(c byte) bool {
  77. return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c > 127
  78. }
  79. // nameChar returns whether c can be a character within an identifier
  80. // (not counting an escape sequence).
  81. func nameChar(c byte) bool {
  82. return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_' || c > 127 ||
  83. c == '-' || '0' <= c && c <= '9'
  84. }
  85. // parseIdentifier parses an identifier.
  86. func (p *parser) parseIdentifier() (result string, err error) {
  87. const prefix = '-'
  88. var numPrefix int
  89. for len(p.s) > p.i && p.s[p.i] == prefix {
  90. p.i++
  91. numPrefix++
  92. }
  93. if len(p.s) <= p.i {
  94. return "", errors.New("expected identifier, found EOF instead")
  95. }
  96. if c := p.s[p.i]; !(nameStart(c) || c == '\\') {
  97. return "", fmt.Errorf("expected identifier, found %c instead", c)
  98. }
  99. result, err = p.parseName()
  100. if numPrefix > 0 && err == nil {
  101. result = strings.Repeat(string(prefix), numPrefix) + result
  102. }
  103. return
  104. }
  105. // parseName parses a name (which is like an identifier, but doesn't have
  106. // extra restrictions on the first character).
  107. func (p *parser) parseName() (result string, err error) {
  108. i := p.i
  109. loop:
  110. for i < len(p.s) {
  111. c := p.s[i]
  112. switch {
  113. case nameChar(c):
  114. start := i
  115. for i < len(p.s) && nameChar(p.s[i]) {
  116. i++
  117. }
  118. result += p.s[start:i]
  119. case c == '\\':
  120. p.i = i
  121. val, err := p.parseEscape()
  122. if err != nil {
  123. return "", err
  124. }
  125. i = p.i
  126. result += val
  127. default:
  128. break loop
  129. }
  130. }
  131. if result == "" {
  132. return "", errors.New("expected name, found EOF instead")
  133. }
  134. p.i = i
  135. return result, nil
  136. }
  137. // parseString parses a single- or double-quoted string.
  138. func (p *parser) parseString() (result string, err error) {
  139. i := p.i
  140. if len(p.s) < i+2 {
  141. return "", errors.New("expected string, found EOF instead")
  142. }
  143. quote := p.s[i]
  144. i++
  145. loop:
  146. for i < len(p.s) {
  147. switch p.s[i] {
  148. case '\\':
  149. if len(p.s) > i+1 {
  150. switch c := p.s[i+1]; c {
  151. case '\r':
  152. if len(p.s) > i+2 && p.s[i+2] == '\n' {
  153. i += 3
  154. continue loop
  155. }
  156. fallthrough
  157. case '\n', '\f':
  158. i += 2
  159. continue loop
  160. }
  161. }
  162. p.i = i
  163. val, err := p.parseEscape()
  164. if err != nil {
  165. return "", err
  166. }
  167. i = p.i
  168. result += val
  169. case quote:
  170. break loop
  171. case '\r', '\n', '\f':
  172. return "", errors.New("unexpected end of line in string")
  173. default:
  174. start := i
  175. for i < len(p.s) {
  176. if c := p.s[i]; c == quote || c == '\\' || c == '\r' || c == '\n' || c == '\f' {
  177. break
  178. }
  179. i++
  180. }
  181. result += p.s[start:i]
  182. }
  183. }
  184. if i >= len(p.s) {
  185. return "", errors.New("EOF in string")
  186. }
  187. // Consume the final quote.
  188. i++
  189. p.i = i
  190. return result, nil
  191. }
  192. // parseRegex parses a regular expression; the end is defined by encountering an
  193. // unmatched closing ')' or ']' which is not consumed
  194. func (p *parser) parseRegex() (rx *regexp.Regexp, err error) {
  195. i := p.i
  196. if len(p.s) < i+2 {
  197. return nil, errors.New("expected regular expression, found EOF instead")
  198. }
  199. // number of open parens or brackets;
  200. // when it becomes negative, finished parsing regex
  201. open := 0
  202. loop:
  203. for i < len(p.s) {
  204. switch p.s[i] {
  205. case '(', '[':
  206. open++
  207. case ')', ']':
  208. open--
  209. if open < 0 {
  210. break loop
  211. }
  212. }
  213. i++
  214. }
  215. if i >= len(p.s) {
  216. return nil, errors.New("EOF in regular expression")
  217. }
  218. rx, err = regexp.Compile(p.s[p.i:i])
  219. p.i = i
  220. return rx, err
  221. }
  222. // skipWhitespace consumes whitespace characters and comments.
  223. // It returns true if there was actually anything to skip.
  224. func (p *parser) skipWhitespace() bool {
  225. i := p.i
  226. for i < len(p.s) {
  227. switch p.s[i] {
  228. case ' ', '\t', '\r', '\n', '\f':
  229. i++
  230. continue
  231. case '/':
  232. if strings.HasPrefix(p.s[i:], "/*") {
  233. end := strings.Index(p.s[i+len("/*"):], "*/")
  234. if end != -1 {
  235. i += end + len("/**/")
  236. continue
  237. }
  238. }
  239. }
  240. break
  241. }
  242. if i > p.i {
  243. p.i = i
  244. return true
  245. }
  246. return false
  247. }
  248. // consumeParenthesis consumes an opening parenthesis and any following
  249. // whitespace. It returns true if there was actually a parenthesis to skip.
  250. func (p *parser) consumeParenthesis() bool {
  251. if p.i < len(p.s) && p.s[p.i] == '(' {
  252. p.i++
  253. p.skipWhitespace()
  254. return true
  255. }
  256. return false
  257. }
  258. // consumeClosingParenthesis consumes a closing parenthesis and any preceding
  259. // whitespace. It returns true if there was actually a parenthesis to skip.
  260. func (p *parser) consumeClosingParenthesis() bool {
  261. i := p.i
  262. p.skipWhitespace()
  263. if p.i < len(p.s) && p.s[p.i] == ')' {
  264. p.i++
  265. return true
  266. }
  267. p.i = i
  268. return false
  269. }
  270. // parseTypeSelector parses a type selector (one that matches by tag name).
  271. func (p *parser) parseTypeSelector() (result tagSelector, err error) {
  272. tag, err := p.parseIdentifier()
  273. if err != nil {
  274. return
  275. }
  276. return tagSelector{tag: toLowerASCII(tag)}, nil
  277. }
  278. // parseIDSelector parses a selector that matches by id attribute.
  279. func (p *parser) parseIDSelector() (idSelector, error) {
  280. if p.i >= len(p.s) {
  281. return idSelector{}, fmt.Errorf("expected id selector (#id), found EOF instead")
  282. }
  283. if p.s[p.i] != '#' {
  284. return idSelector{}, fmt.Errorf("expected id selector (#id), found '%c' instead", p.s[p.i])
  285. }
  286. p.i++
  287. id, err := p.parseName()
  288. if err != nil {
  289. return idSelector{}, err
  290. }
  291. return idSelector{id: id}, nil
  292. }
  293. // parseClassSelector parses a selector that matches by class attribute.
  294. func (p *parser) parseClassSelector() (classSelector, error) {
  295. if p.i >= len(p.s) {
  296. return classSelector{}, fmt.Errorf("expected class selector (.class), found EOF instead")
  297. }
  298. if p.s[p.i] != '.' {
  299. return classSelector{}, fmt.Errorf("expected class selector (.class), found '%c' instead", p.s[p.i])
  300. }
  301. p.i++
  302. class, err := p.parseIdentifier()
  303. if err != nil {
  304. return classSelector{}, err
  305. }
  306. return classSelector{class: class}, nil
  307. }
  308. // parseAttributeSelector parses a selector that matches by attribute value.
  309. func (p *parser) parseAttributeSelector() (attrSelector, error) {
  310. if p.i >= len(p.s) {
  311. return attrSelector{}, fmt.Errorf("expected attribute selector ([attribute]), found EOF instead")
  312. }
  313. if p.s[p.i] != '[' {
  314. return attrSelector{}, fmt.Errorf("expected attribute selector ([attribute]), found '%c' instead", p.s[p.i])
  315. }
  316. p.i++
  317. p.skipWhitespace()
  318. key, err := p.parseIdentifier()
  319. if err != nil {
  320. return attrSelector{}, err
  321. }
  322. key = toLowerASCII(key)
  323. p.skipWhitespace()
  324. if p.i >= len(p.s) {
  325. return attrSelector{}, errors.New("unexpected EOF in attribute selector")
  326. }
  327. if p.s[p.i] == ']' {
  328. p.i++
  329. return attrSelector{key: key, operation: ""}, nil
  330. }
  331. if p.i+2 >= len(p.s) {
  332. return attrSelector{}, errors.New("unexpected EOF in attribute selector")
  333. }
  334. op := p.s[p.i : p.i+2]
  335. if op[0] == '=' {
  336. op = "="
  337. } else if op[1] != '=' {
  338. return attrSelector{}, fmt.Errorf(`expected equality operator, found "%s" instead`, op)
  339. }
  340. p.i += len(op)
  341. p.skipWhitespace()
  342. if p.i >= len(p.s) {
  343. return attrSelector{}, errors.New("unexpected EOF in attribute selector")
  344. }
  345. var val string
  346. var rx *regexp.Regexp
  347. if op == "#=" {
  348. rx, err = p.parseRegex()
  349. } else {
  350. switch p.s[p.i] {
  351. case '\'', '"':
  352. val, err = p.parseString()
  353. default:
  354. val, err = p.parseIdentifier()
  355. }
  356. }
  357. if err != nil {
  358. return attrSelector{}, err
  359. }
  360. p.skipWhitespace()
  361. if p.i >= len(p.s) {
  362. return attrSelector{}, errors.New("unexpected EOF in attribute selector")
  363. }
  364. // check if the attribute contains an ignore case flag
  365. ignoreCase := false
  366. if p.s[p.i] == 'i' || p.s[p.i] == 'I' {
  367. ignoreCase = true
  368. p.i++
  369. }
  370. p.skipWhitespace()
  371. if p.i >= len(p.s) {
  372. return attrSelector{}, errors.New("unexpected EOF in attribute selector")
  373. }
  374. if p.s[p.i] != ']' {
  375. return attrSelector{}, fmt.Errorf("expected ']', found '%c' instead", p.s[p.i])
  376. }
  377. p.i++
  378. switch op {
  379. case "=", "!=", "~=", "|=", "^=", "$=", "*=", "#=":
  380. return attrSelector{key: key, val: val, operation: op, regexp: rx, insensitive: ignoreCase}, nil
  381. default:
  382. return attrSelector{}, fmt.Errorf("attribute operator %q is not supported", op)
  383. }
  384. }
  385. var (
  386. errExpectedParenthesis = errors.New("expected '(' but didn't find it")
  387. errExpectedClosingParenthesis = errors.New("expected ')' but didn't find it")
  388. errUnmatchedParenthesis = errors.New("unmatched '('")
  389. )
  390. // parsePseudoclassSelector parses a pseudoclass selector like :not(p) or a pseudo-element
  391. // For backwards compatibility, both ':' and '::' prefix are allowed for pseudo-elements.
  392. // https://drafts.csswg.org/selectors-3/#pseudo-elements
  393. // Returning a nil `Sel` (and a nil `error`) means we found a pseudo-element.
  394. func (p *parser) parsePseudoclassSelector() (out Sel, pseudoElement string, err error) {
  395. if p.i >= len(p.s) {
  396. return nil, "", fmt.Errorf("expected pseudoclass selector (:pseudoclass), found EOF instead")
  397. }
  398. if p.s[p.i] != ':' {
  399. return nil, "", fmt.Errorf("expected attribute selector (:pseudoclass), found '%c' instead", p.s[p.i])
  400. }
  401. p.i++
  402. var mustBePseudoElement bool
  403. if p.i >= len(p.s) {
  404. return nil, "", fmt.Errorf("got empty pseudoclass (or pseudoelement)")
  405. }
  406. if p.s[p.i] == ':' { // we found a pseudo-element
  407. mustBePseudoElement = true
  408. p.i++
  409. }
  410. name, err := p.parseIdentifier()
  411. if err != nil {
  412. return
  413. }
  414. name = toLowerASCII(name)
  415. if mustBePseudoElement && (name != "after" && name != "backdrop" && name != "before" &&
  416. name != "cue" && name != "first-letter" && name != "first-line" && name != "grammar-error" &&
  417. name != "marker" && name != "placeholder" && name != "selection" && name != "spelling-error") {
  418. return out, "", fmt.Errorf("unknown pseudoelement :%s", name)
  419. }
  420. switch name {
  421. case "not", "has", "haschild":
  422. if !p.consumeParenthesis() {
  423. return out, "", errExpectedParenthesis
  424. }
  425. sel, parseErr := p.parseSelectorGroup()
  426. if parseErr != nil {
  427. return out, "", parseErr
  428. }
  429. if !p.consumeClosingParenthesis() {
  430. return out, "", errExpectedClosingParenthesis
  431. }
  432. out = relativePseudoClassSelector{name: name, match: sel}
  433. case "contains", "containsown":
  434. if !p.consumeParenthesis() {
  435. return out, "", errExpectedParenthesis
  436. }
  437. if p.i == len(p.s) {
  438. return out, "", errUnmatchedParenthesis
  439. }
  440. var val string
  441. switch p.s[p.i] {
  442. case '\'', '"':
  443. val, err = p.parseString()
  444. default:
  445. val, err = p.parseIdentifier()
  446. }
  447. if err != nil {
  448. return out, "", err
  449. }
  450. val = strings.ToLower(val)
  451. p.skipWhitespace()
  452. if p.i >= len(p.s) {
  453. return out, "", errors.New("unexpected EOF in pseudo selector")
  454. }
  455. if !p.consumeClosingParenthesis() {
  456. return out, "", errExpectedClosingParenthesis
  457. }
  458. out = containsPseudoClassSelector{own: name == "containsown", value: val}
  459. case "matches", "matchesown":
  460. if !p.consumeParenthesis() {
  461. return out, "", errExpectedParenthesis
  462. }
  463. rx, err := p.parseRegex()
  464. if err != nil {
  465. return out, "", err
  466. }
  467. if p.i >= len(p.s) {
  468. return out, "", errors.New("unexpected EOF in pseudo selector")
  469. }
  470. if !p.consumeClosingParenthesis() {
  471. return out, "", errExpectedClosingParenthesis
  472. }
  473. out = regexpPseudoClassSelector{own: name == "matchesown", regexp: rx}
  474. case "nth-child", "nth-last-child", "nth-of-type", "nth-last-of-type":
  475. if !p.consumeParenthesis() {
  476. return out, "", errExpectedParenthesis
  477. }
  478. a, b, err := p.parseNth()
  479. if err != nil {
  480. return out, "", err
  481. }
  482. if !p.consumeClosingParenthesis() {
  483. return out, "", errExpectedClosingParenthesis
  484. }
  485. last := name == "nth-last-child" || name == "nth-last-of-type"
  486. ofType := name == "nth-of-type" || name == "nth-last-of-type"
  487. out = nthPseudoClassSelector{a: a, b: b, last: last, ofType: ofType}
  488. case "first-child":
  489. out = nthPseudoClassSelector{a: 0, b: 1, ofType: false, last: false}
  490. case "last-child":
  491. out = nthPseudoClassSelector{a: 0, b: 1, ofType: false, last: true}
  492. case "first-of-type":
  493. out = nthPseudoClassSelector{a: 0, b: 1, ofType: true, last: false}
  494. case "last-of-type":
  495. out = nthPseudoClassSelector{a: 0, b: 1, ofType: true, last: true}
  496. case "only-child":
  497. out = onlyChildPseudoClassSelector{ofType: false}
  498. case "only-of-type":
  499. out = onlyChildPseudoClassSelector{ofType: true}
  500. case "input":
  501. out = inputPseudoClassSelector{}
  502. case "empty":
  503. out = emptyElementPseudoClassSelector{}
  504. case "root":
  505. out = rootPseudoClassSelector{}
  506. case "link":
  507. out = linkPseudoClassSelector{}
  508. case "lang":
  509. if !p.consumeParenthesis() {
  510. return out, "", errExpectedParenthesis
  511. }
  512. if p.i == len(p.s) {
  513. return out, "", errUnmatchedParenthesis
  514. }
  515. val, err := p.parseIdentifier()
  516. if err != nil {
  517. return out, "", err
  518. }
  519. val = strings.ToLower(val)
  520. p.skipWhitespace()
  521. if p.i >= len(p.s) {
  522. return out, "", errors.New("unexpected EOF in pseudo selector")
  523. }
  524. if !p.consumeClosingParenthesis() {
  525. return out, "", errExpectedClosingParenthesis
  526. }
  527. out = langPseudoClassSelector{lang: val}
  528. case "enabled":
  529. out = enabledPseudoClassSelector{}
  530. case "disabled":
  531. out = disabledPseudoClassSelector{}
  532. case "checked":
  533. out = checkedPseudoClassSelector{}
  534. case "visited", "hover", "active", "focus", "target":
  535. // Not applicable in a static context: never match.
  536. out = neverMatchSelector{value: ":" + name}
  537. case "after", "backdrop", "before", "cue", "first-letter", "first-line", "grammar-error", "marker", "placeholder", "selection", "spelling-error":
  538. return nil, name, nil
  539. default:
  540. return out, "", fmt.Errorf("unknown pseudoclass or pseudoelement :%s", name)
  541. }
  542. return
  543. }
  544. // parseInteger parses a decimal integer.
  545. func (p *parser) parseInteger() (int, error) {
  546. i := p.i
  547. start := i
  548. for i < len(p.s) && '0' <= p.s[i] && p.s[i] <= '9' {
  549. i++
  550. }
  551. if i == start {
  552. return 0, errors.New("expected integer, but didn't find it")
  553. }
  554. p.i = i
  555. val, err := strconv.Atoi(p.s[start:i])
  556. if err != nil {
  557. return 0, err
  558. }
  559. return val, nil
  560. }
  561. // parseNth parses the argument for :nth-child (normally of the form an+b).
  562. func (p *parser) parseNth() (a, b int, err error) {
  563. // initial state
  564. if p.i >= len(p.s) {
  565. goto eof
  566. }
  567. switch p.s[p.i] {
  568. case '-':
  569. p.i++
  570. goto negativeA
  571. case '+':
  572. p.i++
  573. goto positiveA
  574. case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
  575. goto positiveA
  576. case 'n', 'N':
  577. a = 1
  578. p.i++
  579. goto readN
  580. case 'o', 'O', 'e', 'E':
  581. id, nameErr := p.parseName()
  582. if nameErr != nil {
  583. return 0, 0, nameErr
  584. }
  585. id = toLowerASCII(id)
  586. if id == "odd" {
  587. return 2, 1, nil
  588. }
  589. if id == "even" {
  590. return 2, 0, nil
  591. }
  592. return 0, 0, fmt.Errorf("expected 'odd' or 'even', but found '%s' instead", id)
  593. default:
  594. goto invalid
  595. }
  596. positiveA:
  597. if p.i >= len(p.s) {
  598. goto eof
  599. }
  600. switch p.s[p.i] {
  601. case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
  602. a, err = p.parseInteger()
  603. if err != nil {
  604. return 0, 0, err
  605. }
  606. goto readA
  607. case 'n', 'N':
  608. a = 1
  609. p.i++
  610. goto readN
  611. default:
  612. goto invalid
  613. }
  614. negativeA:
  615. if p.i >= len(p.s) {
  616. goto eof
  617. }
  618. switch p.s[p.i] {
  619. case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
  620. a, err = p.parseInteger()
  621. if err != nil {
  622. return 0, 0, err
  623. }
  624. a = -a
  625. goto readA
  626. case 'n', 'N':
  627. a = -1
  628. p.i++
  629. goto readN
  630. default:
  631. goto invalid
  632. }
  633. readA:
  634. if p.i >= len(p.s) {
  635. goto eof
  636. }
  637. switch p.s[p.i] {
  638. case 'n', 'N':
  639. p.i++
  640. goto readN
  641. default:
  642. // The number we read as a is actually b.
  643. return 0, a, nil
  644. }
  645. readN:
  646. p.skipWhitespace()
  647. if p.i >= len(p.s) {
  648. goto eof
  649. }
  650. switch p.s[p.i] {
  651. case '+':
  652. p.i++
  653. p.skipWhitespace()
  654. b, err = p.parseInteger()
  655. if err != nil {
  656. return 0, 0, err
  657. }
  658. return a, b, nil
  659. case '-':
  660. p.i++
  661. p.skipWhitespace()
  662. b, err = p.parseInteger()
  663. if err != nil {
  664. return 0, 0, err
  665. }
  666. return a, -b, nil
  667. default:
  668. return a, 0, nil
  669. }
  670. eof:
  671. return 0, 0, errors.New("unexpected EOF while attempting to parse expression of form an+b")
  672. invalid:
  673. return 0, 0, errors.New("unexpected character while attempting to parse expression of form an+b")
  674. }
  675. // parseSimpleSelectorSequence parses a selector sequence that applies to
  676. // a single element.
  677. func (p *parser) parseSimpleSelectorSequence() (Sel, error) {
  678. var selectors []Sel
  679. if p.i >= len(p.s) {
  680. return nil, errors.New("expected selector, found EOF instead")
  681. }
  682. switch p.s[p.i] {
  683. case '*':
  684. // It's the universal selector. Just skip over it, since it doesn't affect the meaning.
  685. p.i++
  686. if p.i+2 < len(p.s) && p.s[p.i:p.i+2] == "|*" { // other version of universal selector
  687. p.i += 2
  688. }
  689. case '#', '.', '[', ':':
  690. // There's no type selector. Wait to process the other till the main loop.
  691. default:
  692. r, err := p.parseTypeSelector()
  693. if err != nil {
  694. return nil, err
  695. }
  696. selectors = append(selectors, r)
  697. }
  698. var pseudoElement string
  699. loop:
  700. for p.i < len(p.s) {
  701. var (
  702. ns Sel
  703. newPseudoElement string
  704. err error
  705. )
  706. switch p.s[p.i] {
  707. case '#':
  708. ns, err = p.parseIDSelector()
  709. case '.':
  710. ns, err = p.parseClassSelector()
  711. case '[':
  712. ns, err = p.parseAttributeSelector()
  713. case ':':
  714. ns, newPseudoElement, err = p.parsePseudoclassSelector()
  715. default:
  716. break loop
  717. }
  718. if err != nil {
  719. return nil, err
  720. }
  721. // From https://drafts.csswg.org/selectors-3/#pseudo-elements :
  722. // "Only one pseudo-element may appear per selector, and if present
  723. // it must appear after the sequence of simple selectors that
  724. // represents the subjects of the selector.""
  725. if ns == nil { // we found a pseudo-element
  726. if pseudoElement != "" {
  727. return nil, fmt.Errorf("only one pseudo-element is accepted per selector, got %s and %s", pseudoElement, newPseudoElement)
  728. }
  729. if !p.acceptPseudoElements {
  730. return nil, fmt.Errorf("pseudo-element %s found, but pseudo-elements support is disabled", newPseudoElement)
  731. }
  732. pseudoElement = newPseudoElement
  733. } else {
  734. if pseudoElement != "" {
  735. return nil, fmt.Errorf("pseudo-element %s must be at the end of selector", pseudoElement)
  736. }
  737. selectors = append(selectors, ns)
  738. }
  739. }
  740. if len(selectors) == 1 && pseudoElement == "" { // no need wrap the selectors in compoundSelector
  741. return selectors[0], nil
  742. }
  743. return compoundSelector{selectors: selectors, pseudoElement: pseudoElement}, nil
  744. }
  745. // parseSelector parses a selector that may include combinators.
  746. func (p *parser) parseSelector() (Sel, error) {
  747. p.skipWhitespace()
  748. result, err := p.parseSimpleSelectorSequence()
  749. if err != nil {
  750. return nil, err
  751. }
  752. for {
  753. var (
  754. combinator byte
  755. c Sel
  756. )
  757. if p.skipWhitespace() {
  758. combinator = ' '
  759. }
  760. if p.i >= len(p.s) {
  761. return result, nil
  762. }
  763. switch p.s[p.i] {
  764. case '+', '>', '~':
  765. combinator = p.s[p.i]
  766. p.i++
  767. p.skipWhitespace()
  768. case ',', ')':
  769. // These characters can't begin a selector, but they can legally occur after one.
  770. return result, nil
  771. }
  772. if combinator == 0 {
  773. return result, nil
  774. }
  775. c, err = p.parseSimpleSelectorSequence()
  776. if err != nil {
  777. return nil, err
  778. }
  779. result = combinedSelector{first: result, combinator: combinator, second: c}
  780. }
  781. }
  782. // parseSelectorGroup parses a group of selectors, separated by commas.
  783. func (p *parser) parseSelectorGroup() (SelectorGroup, error) {
  784. current, err := p.parseSelector()
  785. if err != nil {
  786. return nil, err
  787. }
  788. result := SelectorGroup{current}
  789. for p.i < len(p.s) {
  790. if p.s[p.i] != ',' {
  791. break
  792. }
  793. p.i++
  794. c, err := p.parseSelector()
  795. if err != nil {
  796. return nil, err
  797. }
  798. result = append(result, c)
  799. }
  800. return result, nil
  801. }