jade_lex.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. package jade
  2. import (
  3. "strings"
  4. )
  5. func lexIndents(l *lexer) stateFn {
  6. d := l.indents()
  7. if d == -1 {
  8. l.depth = 0
  9. l.emit(itemEmptyLine)
  10. } else {
  11. l.depth = d
  12. l.emit(itemIdent)
  13. }
  14. return lexTags
  15. }
  16. func (l *lexer) indents() (depth int) {
  17. for {
  18. switch l.next() {
  19. case ' ':
  20. depth += 1
  21. case '\t':
  22. depth += TabSize
  23. case '\r':
  24. // skip
  25. case '\n':
  26. return -1
  27. default:
  28. l.backup()
  29. return
  30. }
  31. }
  32. }
  33. func lexEndLine(l *lexer) stateFn {
  34. switch r := l.next(); {
  35. case r == '\r':
  36. if l.next() == '\n' {
  37. l.emit(itemEndL)
  38. return lexIndents
  39. }
  40. return l.errorf("lexTags: standalone '\\r' ")
  41. case r == '\n':
  42. l.emit(itemEndL)
  43. return lexIndents
  44. case r == eof:
  45. l.depth = 0
  46. l.emit(itemEOF)
  47. return nil
  48. default:
  49. return l.errorf("lexEndLine: unexpected token %#U `%s`", r, string(r))
  50. }
  51. }
  52. // lexTags scans tags.
  53. func lexTags(l *lexer) stateFn {
  54. switch r := l.next(); {
  55. case isEndOfLine(r), r == eof:
  56. l.backup()
  57. return lexEndLine
  58. case r == ' ' || r == '\t':
  59. l.backup()
  60. return lexIndents
  61. //
  62. //
  63. case r == '.':
  64. n := l.skipSpaces()
  65. if n == 0 {
  66. l.emit(itemDiv)
  67. return lexClass
  68. }
  69. if n == -1 {
  70. l.ignore()
  71. return lexLongText
  72. }
  73. return l.errorf("lexTags: class name cannot start with a space.")
  74. case r == '#':
  75. l.emit(itemDiv)
  76. return lexID
  77. case r == ':':
  78. l.ignore()
  79. if l.emitWordByType(itemFilter) {
  80. r = l.next()
  81. if r == ':' {
  82. l.ignore()
  83. l.emitWordByType(itemFilterSubf)
  84. r = l.next()
  85. }
  86. if r == '(' {
  87. l.ignore()
  88. l.toStopRune(')', true)
  89. l.emit(itemFilterArgs)
  90. l.next()
  91. l.ignore()
  92. } else {
  93. l.backup()
  94. }
  95. return lexFilter
  96. }
  97. return l.errorf("lexTags: expect filter name")
  98. case r == '|':
  99. r = l.next()
  100. if r != ' ' {
  101. l.backup()
  102. }
  103. l.ignore()
  104. return lexText
  105. case r == '<':
  106. l.emitLineByType(itemHTMLTag)
  107. return lexEndLine
  108. case r == '+':
  109. l.skipSpaces()
  110. l.ignore()
  111. if l.emitWordByType(itemMixinCall) {
  112. return lexAfterTag
  113. }
  114. return l.errorf("lexTags: expect mixin name")
  115. case r == '/':
  116. return lexComment
  117. case r == '-':
  118. l.ignore()
  119. return lexCode
  120. case r == '=':
  121. l.skipSpaces()
  122. l.ignore()
  123. l.emitLineByType(itemCodeBuffered)
  124. return lexEndLine
  125. case r == '!':
  126. np := l.next()
  127. if np == '=' {
  128. l.skipSpaces()
  129. l.ignore()
  130. l.emitLineByType(itemCodeUnescaped)
  131. return lexEndLine
  132. }
  133. if np == '!' && l.next() == '!' && l.depth == 0 {
  134. l.ignore()
  135. if l.skipSpaces() != -1 {
  136. l.emitLineByType(itemDoctype)
  137. } else {
  138. l.emit(itemDoctype)
  139. }
  140. return lexEndLine
  141. }
  142. return l.errorf("expect '=' after '!'")
  143. case isAlphaNumeric(r):
  144. l.backup()
  145. return lexTagName
  146. default:
  147. return l.errorf("lexTags: unexpected token %#U `%s`", r, string(r))
  148. }
  149. }
  150. //
  151. //
  152. func lexID(l *lexer) stateFn {
  153. if l.emitWordByType(itemID) {
  154. return lexAfterTag
  155. }
  156. return l.errorf("lexID: expect id name")
  157. }
  158. func lexClass(l *lexer) stateFn {
  159. if l.emitWordByType(itemClass) {
  160. return lexAfterTag
  161. }
  162. return l.errorf("lexClass: expect class name")
  163. }
  164. func lexFilter(l *lexer) stateFn {
  165. l.multiline()
  166. l.emit(itemFilterText)
  167. return lexIndents
  168. }
  169. func lexCode(l *lexer) stateFn {
  170. if l.skipSpaces() == -1 {
  171. l.multiline()
  172. l.emit(itemCode)
  173. return lexIndents
  174. } else {
  175. l.ignore()
  176. l.emitLineByType(itemCode)
  177. return lexEndLine
  178. }
  179. }
  180. func lexComment(l *lexer) stateFn {
  181. sp := l.next()
  182. tp := l.peek()
  183. if sp == '/' {
  184. if tp == '-' {
  185. l.multiline()
  186. l.ignore()
  187. return lexIndents
  188. } else {
  189. l.ignore()
  190. l.multiline()
  191. l.emit(itemComment)
  192. return lexIndents
  193. }
  194. }
  195. return l.errorf("lexComment: unexpected token '%#U' expect '/'", sp)
  196. }
  197. //
  198. //
  199. func lexText(l *lexer) stateFn {
  200. if l.skipSpaces() == -1 {
  201. l.ignore()
  202. return lexEndLine
  203. }
  204. return text(l)
  205. }
  206. func lexLongText(l *lexer) stateFn {
  207. l.longtext = true
  208. return text(l)
  209. }
  210. func text(l *lexer) stateFn {
  211. for {
  212. switch r := l.next(); {
  213. case r == '\\':
  214. l.next()
  215. continue
  216. case r == '#':
  217. sp := l.peek()
  218. if sp == '[' {
  219. l.backup()
  220. if l.pos > l.start {
  221. l.emit(itemText)
  222. }
  223. l.next()
  224. l.next()
  225. l.skipSpaces()
  226. l.interpolation += 1
  227. l.depth += 1
  228. // l.emit(itemInterpolation)
  229. l.ignore()
  230. return lexTags
  231. }
  232. if sp == '{' {
  233. l.interpol(itemCodeBuffered)
  234. }
  235. // case r == '$':
  236. // sp := l.peek()
  237. // if sp == '{' {
  238. // l.interpol(itemCodeBuffered)
  239. // }
  240. case r == '!':
  241. sp := l.peek()
  242. if sp == '{' {
  243. l.interpol(itemCodeUnescaped)
  244. }
  245. case r == ']':
  246. if l.interpolation > 0 {
  247. l.backup()
  248. if l.pos > l.start {
  249. l.emit(itemText)
  250. }
  251. l.next()
  252. // l.emit(itemInterpolationEnd)
  253. l.ignore()
  254. l.interpolation -= 1
  255. l.depth -= 1
  256. }
  257. case r == eof:
  258. l.backup()
  259. l.emit(itemText)
  260. return lexEndLine
  261. case r == '\n':
  262. if l.longtext {
  263. var (
  264. indent int
  265. pos pos
  266. )
  267. l.backup()
  268. pos = l.pos
  269. l.next()
  270. indent = l.indents()
  271. if indent != -1 {
  272. if indent < l.depth {
  273. l.pos = pos
  274. if l.pos > l.start {
  275. l.emit(itemText)
  276. }
  277. l.longtext = false
  278. return lexIndents
  279. }
  280. } else {
  281. l.backup()
  282. }
  283. } else {
  284. l.backup()
  285. if l.pos > l.start {
  286. l.emit(itemText)
  287. }
  288. return lexIndents
  289. }
  290. }
  291. }
  292. }
  293. func (l *lexer) interpol(item itemType) {
  294. l.backup()
  295. if l.pos > l.start {
  296. l.emit(itemText)
  297. }
  298. l.next()
  299. l.next()
  300. l.skipSpaces()
  301. l.ignore()
  302. Loop:
  303. for {
  304. switch r := l.next(); {
  305. case r == '`':
  306. l.toStopRune('`', false)
  307. case r == '"':
  308. l.toStopRune('"', false)
  309. case r == '\'':
  310. l.toStopRune('\'', false)
  311. case r == '\n', r == eof:
  312. l.backup()
  313. l.errorf("interpolation error: expect '}'")
  314. return
  315. case r == '}':
  316. break Loop
  317. }
  318. }
  319. l.backup()
  320. l.emit(item)
  321. l.next()
  322. l.ignore()
  323. }
  324. func lexTagName(l *lexer) stateFn {
  325. for {
  326. switch r := l.next(); {
  327. case isAlphaNumeric(r):
  328. // absorb.
  329. default:
  330. l.backup()
  331. word := l.input[l.start:l.pos]
  332. if w, ok := key[word]; ok {
  333. switch w {
  334. case itemElse:
  335. l.emit(w)
  336. l.skipSpaces()
  337. l.ignore()
  338. return lexTags
  339. case itemDoctype, itemExtends:
  340. if l.depth == 0 {
  341. ss := l.skipSpaces()
  342. l.ignore()
  343. if ss != -1 {
  344. l.emitLineByType(w)
  345. } else if w == itemDoctype {
  346. l.emit(w)
  347. } else {
  348. return l.errorf("lexTagName: itemExtends need path ")
  349. }
  350. return lexEndLine
  351. } else {
  352. l.emit(itemTag)
  353. }
  354. case itemBlock:
  355. sp := l.skipSpaces()
  356. l.ignore()
  357. if sp == -1 {
  358. l.emit(itemMixinBlock)
  359. } else if strings.HasPrefix(l.input[l.pos:], "prepend ") {
  360. l.toStopRune(' ', true)
  361. l.skipSpaces()
  362. l.ignore()
  363. l.emitLineByType(itemBlockPrepend)
  364. } else if strings.HasPrefix(l.input[l.pos:], "append ") {
  365. l.toStopRune(' ', true)
  366. l.skipSpaces()
  367. l.ignore()
  368. l.emitLineByType(itemBlockAppend)
  369. } else {
  370. l.emitLineByType(itemBlock)
  371. }
  372. return lexEndLine
  373. case itemBlockAppend, itemBlockPrepend,
  374. itemIf, itemUnless, itemCase,
  375. itemEach, itemWhile, itemFor,
  376. itemInclude:
  377. l.skipSpaces()
  378. l.ignore()
  379. l.emitLineByType(w)
  380. return lexEndLine
  381. case itemMixin:
  382. l.skipSpaces()
  383. l.ignore()
  384. l.emitWordByType(w)
  385. return lexAfterTag
  386. case itemCaseWhen:
  387. l.skipSpaces()
  388. l.ignore()
  389. l.toStopRune(':', true)
  390. l.emit(w)
  391. return lexAfterTag
  392. default:
  393. l.emit(w)
  394. }
  395. } else {
  396. l.emit(itemTag)
  397. }
  398. return lexAfterTag
  399. }
  400. }
  401. }
  402. func lexAfterTag(l *lexer) stateFn {
  403. switch r := l.next(); {
  404. case r == '(':
  405. l.emit(itemAttrStart)
  406. return lexAttr
  407. case r == '/':
  408. l.emit(itemTagEnd)
  409. return lexAfterTag
  410. case r == ':':
  411. l.skipSpaces()
  412. l.ignore()
  413. l.depth += 1
  414. return lexTags
  415. case r == ' ' || r == '\t':
  416. l.ignore()
  417. l.depth += 1
  418. return lexText
  419. case r == ']':
  420. if l.interpolation > 0 {
  421. l.ignore()
  422. if l.pos > l.start {
  423. l.emit(itemText)
  424. }
  425. l.interpolation -= 1
  426. l.depth -= 1
  427. if l.longtext {
  428. return lexLongText
  429. } else {
  430. return lexText
  431. }
  432. }
  433. return l.errorf("lexAfterTag: %#U", r)
  434. case r == '=':
  435. l.skipSpaces()
  436. l.ignore()
  437. l.depth += 1
  438. l.emitLineByType(itemCodeBuffered)
  439. return lexEndLine
  440. case r == '!':
  441. if l.next() == '=' {
  442. l.skipSpaces()
  443. l.ignore()
  444. l.depth += 1
  445. l.emitLineByType(itemCodeUnescaped)
  446. return lexEndLine
  447. }
  448. return l.errorf("expect '=' after '!'")
  449. case r == '#':
  450. l.ignore()
  451. return lexID
  452. case r == '&':
  453. l.toStopRune(')', false)
  454. l.ignore() // TODO: now ignore div(data-bar="foo")&attributes({'data-foo': 'baz'})
  455. return lexAfterTag
  456. case r == '.':
  457. switch l.skipSpaces() {
  458. case 0:
  459. l.ignore()
  460. return lexClass
  461. case -1:
  462. if sp := l.next(); sp != eof {
  463. l.ignore()
  464. l.depth += 1
  465. return lexLongText
  466. }
  467. return lexEndLine
  468. default:
  469. l.ignore()
  470. l.depth += 1
  471. return lexText
  472. }
  473. case isEndOfLine(r), r == eof:
  474. l.backup()
  475. return lexEndLine
  476. default:
  477. return l.errorf("lexAfterTag: %#U", r)
  478. }
  479. }
  480. //
  481. //
  482. func lexAttr(l *lexer) stateFn {
  483. b1, b2, b3 := 0, 0, 0
  484. for {
  485. switch r := l.next(); {
  486. case r == '"' || r == '\'':
  487. l.toStopRune(r, false)
  488. case r == '`':
  489. for {
  490. r = l.next()
  491. if r == '`' {
  492. break
  493. }
  494. }
  495. case r == '(':
  496. // b1 += 1
  497. l.toStopRune(')', false)
  498. case r == ')':
  499. // b1 -= 1
  500. // if b1 == -1 {
  501. if b2 != 0 || b3 != 0 {
  502. return l.errorf("lexAttrName: mismatched bracket")
  503. }
  504. l.backup()
  505. if l.pos > l.start {
  506. l.emit(itemAttr)
  507. }
  508. l.next()
  509. l.emit(itemAttrEnd)
  510. return lexAfterTag
  511. // }
  512. case r == '[':
  513. b2 += 1
  514. case r == ']':
  515. b2 -= 1
  516. if b2 == -1 {
  517. return l.errorf("lexAttrName: mismatched bracket '['")
  518. }
  519. case r == '{':
  520. b3 += 1
  521. case r == '}':
  522. b3 -= 1
  523. if b3 == -1 {
  524. return l.errorf("lexAttrName: mismatched bracket '{'")
  525. }
  526. case r == ' ' || r == '\t':
  527. l.backup()
  528. if l.pos > l.start {
  529. l.emit(itemAttr)
  530. }
  531. l.skipSpaces()
  532. l.emit(itemAttrSpace)
  533. case r == '=':
  534. if l.peek() == '=' {
  535. l.toStopRune(' ', true)
  536. l.emit(itemAttr)
  537. continue
  538. }
  539. l.backup()
  540. l.emit(itemAttr)
  541. l.next()
  542. l.emit(itemAttrEqual)
  543. case r == '!':
  544. if l.peek() == '=' {
  545. l.backup()
  546. l.emit(itemAttr)
  547. l.next()
  548. l.next()
  549. l.emit(itemAttrEqualUn)
  550. }
  551. case r == ',' || r == '\n':
  552. if b1 == 0 && b2 == 0 && b3 == 0 {
  553. l.backup()
  554. if l.pos > l.start {
  555. l.emit(itemAttr)
  556. }
  557. l.next()
  558. l.emit(itemAttrComma)
  559. }
  560. case r == eof:
  561. return l.errorf("lexAttr: expected ')'")
  562. }
  563. }
  564. }
  565. //
  566. //
  567. //
  568. //
  569. //
  570. //
  571. //
  572. //
  573. //
  574. //
  575. func (l *lexer) emitWordByType(item itemType) bool {
  576. for {
  577. if !isAlphaNumeric(l.next()) {
  578. l.backup()
  579. break
  580. }
  581. }
  582. if l.pos > l.start {
  583. l.emit(item)
  584. return true
  585. }
  586. return false
  587. }
  588. func (l *lexer) emitLineByType(item itemType) bool {
  589. var r rune
  590. for {
  591. r = l.next()
  592. if r == '\n' || r == '\r' || r == eof {
  593. l.backup()
  594. if l.pos > l.start {
  595. l.emit(item)
  596. return true
  597. }
  598. return false
  599. }
  600. }
  601. }
  602. //
  603. func (l *lexer) skipSpaces() (out int) {
  604. for {
  605. switch l.next() {
  606. case ' ', '\t':
  607. out += 1
  608. case '\n', eof:
  609. l.backup()
  610. return -1
  611. default:
  612. l.backup()
  613. return
  614. }
  615. }
  616. }
  617. func (l *lexer) toStopRune(stopRune rune, backup bool) {
  618. for {
  619. switch r := l.next(); {
  620. case r == stopRune:
  621. if backup {
  622. l.backup()
  623. }
  624. return
  625. case r == eof || r == '\r' || r == '\n':
  626. l.backup()
  627. return
  628. }
  629. }
  630. }
  631. func (l *lexer) multiline() {
  632. var (
  633. indent int
  634. pos pos
  635. )
  636. for {
  637. switch r := l.next(); {
  638. case r == '\n':
  639. l.backup()
  640. pos = l.pos
  641. l.next()
  642. indent = l.indents()
  643. if indent != -1 {
  644. if indent <= l.depth {
  645. l.pos = pos
  646. return
  647. }
  648. } else {
  649. l.backup()
  650. }
  651. case r == eof:
  652. l.backup()
  653. return
  654. }
  655. }
  656. }