parse.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. // Copyright 2016 José Santos <henrique_1609@me.com>
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package jet
  15. import (
  16. "bytes"
  17. "fmt"
  18. "runtime"
  19. "strconv"
  20. "strings"
  21. )
  22. func unquote(text string) (string, error) {
  23. return strconv.Unquote(text)
  24. }
  25. // Template is the representation of a single parsed template.
  26. type Template struct {
  27. Name string // name of the template represented by the tree.
  28. ParseName string // name of the top-level template during parsing, for error messages.
  29. set *Set
  30. extends *Template
  31. imports []*Template
  32. processedBlocks map[string]*BlockNode
  33. passedBlocks map[string]*BlockNode
  34. Root *ListNode // top-level root of the tree.
  35. text string // text parsed to create the template (or its parent)
  36. // Parsing only; cleared after parse.
  37. lex *lexer
  38. token [3]item // three-token lookahead for parser.
  39. peekCount int
  40. }
  41. func (t *Template) String() (template string) {
  42. if t.extends != nil {
  43. if len(t.Root.Nodes) > 0 && len(t.imports) == 0 {
  44. template += fmt.Sprintf("{{extends %q}}", t.extends.ParseName)
  45. } else {
  46. template += fmt.Sprintf("{{extends %q}}", t.extends.ParseName)
  47. }
  48. }
  49. for k, _import := range t.imports {
  50. if t.extends == nil && k == 0 {
  51. template += fmt.Sprintf("{{import %q}}", _import.ParseName)
  52. } else {
  53. template += fmt.Sprintf("\n{{import %q}}", _import.ParseName)
  54. }
  55. }
  56. if t.extends != nil || len(t.imports) > 0 {
  57. if len(t.Root.Nodes) > 0 {
  58. template += "\n" + t.Root.String()
  59. }
  60. } else {
  61. template += t.Root.String()
  62. }
  63. return
  64. }
  65. func (t *Template) addBlocks(blocks map[string]*BlockNode) {
  66. if len(blocks) == 0 {
  67. return
  68. }
  69. if t.processedBlocks == nil {
  70. t.processedBlocks = make(map[string]*BlockNode)
  71. }
  72. for key, value := range blocks {
  73. t.processedBlocks[key] = value
  74. }
  75. }
  76. // next returns the next token.
  77. func (t *Template) next() item {
  78. if t.peekCount > 0 {
  79. t.peekCount--
  80. } else {
  81. t.token[0] = t.lex.nextItem()
  82. }
  83. return t.token[t.peekCount]
  84. }
  85. // backup backs the input stream up one token.
  86. func (t *Template) backup() {
  87. t.peekCount++
  88. }
  89. // backup2 backs the input stream up two tokens.
  90. // The zeroth token is already there.
  91. func (t *Template) backup2(t1 item) {
  92. t.token[1] = t1
  93. t.peekCount = 2
  94. }
  95. // backup3 backs the input stream up three tokens
  96. // The zeroth token is already there.
  97. func (t *Template) backup3(t2, t1 item) {
  98. // Reverse order: we're pushing back.
  99. t.token[1] = t1
  100. t.token[2] = t2
  101. t.peekCount = 3
  102. }
  103. // peek returns but does not consume the next token.
  104. func (t *Template) peek() item {
  105. if t.peekCount > 0 {
  106. return t.token[t.peekCount-1]
  107. }
  108. t.peekCount = 1
  109. t.token[0] = t.lex.nextItem()
  110. return t.token[0]
  111. }
  112. // nextNonSpace returns the next non-space token.
  113. func (t *Template) nextNonSpace() (token item) {
  114. for {
  115. token = t.next()
  116. if token.typ != itemSpace {
  117. break
  118. }
  119. }
  120. return token
  121. }
  122. // peekNonSpace returns but does not consume the next non-space token.
  123. func (t *Template) peekNonSpace() (token item) {
  124. for {
  125. token = t.next()
  126. if token.typ != itemSpace {
  127. break
  128. }
  129. }
  130. t.backup()
  131. return token
  132. }
  133. // errorf formats the error and terminates processing.
  134. func (t *Template) errorf(format string, args ...interface{}) {
  135. t.Root = nil
  136. format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
  137. panic(fmt.Errorf(format, args...))
  138. }
  139. // error terminates processing.
  140. func (t *Template) error(err error) {
  141. t.errorf("%s", err)
  142. }
  143. // expect consumes the next token and guarantees it has the required type.
  144. func (t *Template) expect(expectedType itemType, context, expected string) item {
  145. token := t.nextNonSpace()
  146. if token.typ != expectedType {
  147. t.unexpected(token, context, expected)
  148. }
  149. return token
  150. }
  151. func (t *Template) expectRightDelim(context string) item {
  152. return t.expect(itemRightDelim, context, "closing delimiter")
  153. }
  154. // expectOneOf consumes the next token and guarantees it has one of the required types.
  155. func (t *Template) expectOneOf(expected1, expected2 itemType, context, expectedAs string) item {
  156. token := t.nextNonSpace()
  157. if token.typ != expected1 && token.typ != expected2 {
  158. t.unexpected(token, context, expectedAs)
  159. }
  160. return token
  161. }
  162. // unexpected complains about the token and terminates processing.
  163. func (t *Template) unexpected(token item, context, expected string) {
  164. switch {
  165. case token.typ == itemImport,
  166. token.typ == itemExtends:
  167. t.errorf("parsing %s: unexpected keyword '%s' ('%s' statements must be at the beginning of the template)", context, token.val, token.val)
  168. case token.typ > itemKeyword:
  169. t.errorf("parsing %s: unexpected keyword '%s' (expected %s)", context, token.val, expected)
  170. default:
  171. t.errorf("parsing %s: unexpected token '%s' (expected %s)", context, token.val, expected)
  172. }
  173. }
  174. // recover is the handler that turns panics into returns from the top level of Parse.
  175. func (t *Template) recover(errp *error) {
  176. e := recover()
  177. if e != nil {
  178. if _, ok := e.(runtime.Error); ok {
  179. panic(e)
  180. }
  181. if t != nil {
  182. t.lex.drain()
  183. t.stopParse()
  184. }
  185. *errp = e.(error)
  186. }
  187. return
  188. }
  189. func (s *Set) parse(name, text string, cacheAfterParsing bool) (t *Template, err error) {
  190. t = &Template{
  191. Name: name,
  192. ParseName: name,
  193. text: text,
  194. set: s,
  195. passedBlocks: make(map[string]*BlockNode),
  196. }
  197. defer t.recover(&err)
  198. lexer := lex(name, text, false)
  199. lexer.setDelimiters(s.leftDelim, s.rightDelim)
  200. lexer.run()
  201. t.startParse(lexer)
  202. t.parseTemplate(cacheAfterParsing)
  203. t.stopParse()
  204. if t.extends != nil {
  205. t.addBlocks(t.extends.processedBlocks)
  206. }
  207. for _, _import := range t.imports {
  208. t.addBlocks(_import.processedBlocks)
  209. }
  210. t.addBlocks(t.passedBlocks)
  211. return t, err
  212. }
  213. func (t *Template) expectString(context string) string {
  214. token := t.expectOneOf(itemString, itemRawString, context, "string literal")
  215. s, err := unquote(token.val)
  216. if err != nil {
  217. t.error(err)
  218. }
  219. return s
  220. }
  221. // parse is the top-level parser for a template, essentially the same
  222. // It runs to EOF.
  223. func (t *Template) parseTemplate(cacheAfterParsing bool) (next Node) {
  224. t.Root = t.newList(t.peek().pos)
  225. // {{ extends|import stringLiteral }}
  226. for t.peek().typ != itemEOF {
  227. delim := t.next()
  228. if delim.typ == itemText && strings.TrimSpace(delim.val) == "" {
  229. continue //skips empty text nodes
  230. }
  231. if delim.typ == itemLeftDelim {
  232. token := t.nextNonSpace()
  233. if token.typ == itemExtends || token.typ == itemImport {
  234. s := t.expectString("extends|import")
  235. if token.typ == itemExtends {
  236. if t.extends != nil {
  237. t.errorf("Unexpected extends clause: each template can only extend one template")
  238. } else if len(t.imports) > 0 {
  239. t.errorf("Unexpected extends clause: the 'extends' clause should come before all import clauses")
  240. }
  241. var err error
  242. t.extends, err = t.set.getSiblingTemplate(s, t.Name, cacheAfterParsing)
  243. if err != nil {
  244. t.error(err)
  245. }
  246. } else {
  247. tt, err := t.set.getSiblingTemplate(s, t.Name, cacheAfterParsing)
  248. if err != nil {
  249. t.error(err)
  250. }
  251. t.imports = append(t.imports, tt)
  252. }
  253. t.expect(itemRightDelim, "extends|import", "closing delimiter")
  254. } else {
  255. t.backup2(delim)
  256. break
  257. }
  258. } else {
  259. t.backup()
  260. break
  261. }
  262. }
  263. for t.peek().typ != itemEOF {
  264. switch n := t.textOrAction(); n.Type() {
  265. case nodeEnd, nodeElse, nodeContent:
  266. t.errorf("unexpected %s", n)
  267. default:
  268. t.Root.append(n)
  269. }
  270. }
  271. return nil
  272. }
  273. // startParse initializes the parser, using the lexer.
  274. func (t *Template) startParse(lex *lexer) {
  275. t.Root = nil
  276. t.lex = lex
  277. }
  278. // stopParse terminates parsing.
  279. func (t *Template) stopParse() {
  280. t.lex = nil
  281. }
  282. // IsEmptyTree reports whether this tree (node) is empty of everything but space.
  283. func IsEmptyTree(n Node) bool {
  284. switch n := n.(type) {
  285. case nil:
  286. return true
  287. case *ActionNode:
  288. case *IfNode:
  289. case *ListNode:
  290. for _, node := range n.Nodes {
  291. if !IsEmptyTree(node) {
  292. return false
  293. }
  294. }
  295. return true
  296. case *RangeNode:
  297. case *IncludeNode:
  298. case *TextNode:
  299. return len(bytes.TrimSpace(n.Text)) == 0
  300. case *BlockNode:
  301. case *YieldNode:
  302. default:
  303. panic("unknown node: " + n.String())
  304. }
  305. return false
  306. }
  307. func (t *Template) blockParametersList(isDeclaring bool, context string) *BlockParameterList {
  308. block := &BlockParameterList{}
  309. t.expect(itemLeftParen, context, "opening parenthesis")
  310. for {
  311. var expression Expression
  312. next := t.nextNonSpace()
  313. if next.typ == itemIdentifier {
  314. identifier := next.val
  315. next2 := t.nextNonSpace()
  316. switch next2.typ {
  317. case itemComma, itemRightParen:
  318. block.List = append(block.List, BlockParameter{Identifier: identifier})
  319. next = next2
  320. case itemAssign:
  321. expression, next = t.parseExpression(context)
  322. block.List = append(block.List, BlockParameter{Identifier: identifier, Expression: expression})
  323. default:
  324. if !isDeclaring {
  325. switch next2.typ {
  326. case itemComma, itemRightParen:
  327. default:
  328. t.backup2(next)
  329. expression, next = t.parseExpression(context)
  330. block.List = append(block.List, BlockParameter{Expression: expression})
  331. }
  332. } else {
  333. t.unexpected(next2, context, "comma, assignment, or closing parenthesis")
  334. }
  335. }
  336. } else if !isDeclaring {
  337. switch next.typ {
  338. case itemComma, itemRightParen:
  339. default:
  340. t.backup()
  341. expression, next = t.parseExpression(context)
  342. block.List = append(block.List, BlockParameter{Expression: expression})
  343. }
  344. }
  345. if next.typ != itemComma {
  346. t.backup()
  347. break
  348. }
  349. }
  350. t.expect(itemRightParen, context, "closing parenthesis")
  351. return block
  352. }
  353. func (t *Template) parseBlock() Node {
  354. const context = "block clause"
  355. var pipe Expression
  356. name := t.expect(itemIdentifier, context, "name")
  357. bplist := t.blockParametersList(true, context)
  358. if t.peekNonSpace().typ != itemRightDelim {
  359. pipe = t.expression(context, "context")
  360. }
  361. t.expectRightDelim(context)
  362. list, end := t.itemList(nodeContent, nodeEnd)
  363. var contentList *ListNode
  364. if end.Type() == nodeContent {
  365. contentList, end = t.itemList(nodeEnd)
  366. }
  367. block := t.newBlock(name.pos, t.lex.lineNumber(), name.val, bplist, pipe, list, contentList)
  368. t.passedBlocks[block.Name] = block
  369. return block
  370. }
  371. func (t *Template) parseYield() Node {
  372. const context = "yield clause"
  373. var (
  374. pipe Expression
  375. name item
  376. bplist *BlockParameterList
  377. content *ListNode
  378. )
  379. // parse block name
  380. name = t.nextNonSpace()
  381. if name.typ == itemContent {
  382. // content yield {{yield content}}
  383. if t.peekNonSpace().typ != itemRightDelim {
  384. pipe = t.expression(context, "content context")
  385. }
  386. t.expectRightDelim(context)
  387. return t.newYield(name.pos, t.lex.lineNumber(), "", nil, pipe, nil, true)
  388. } else if name.typ != itemIdentifier {
  389. t.unexpected(name, context, "block name")
  390. }
  391. // parse block parameters
  392. bplist = t.blockParametersList(false, context)
  393. // parse optional context & content
  394. typ := t.peekNonSpace().typ
  395. if typ == itemRightDelim {
  396. t.expectRightDelim(context)
  397. } else {
  398. if typ != itemContent {
  399. // parse context expression
  400. pipe = t.expression("yield", "context")
  401. typ = t.peekNonSpace().typ
  402. }
  403. if typ == itemRightDelim {
  404. t.expectRightDelim(context)
  405. } else if typ == itemContent {
  406. // parse content from following nodes (until {{end}})
  407. t.nextNonSpace()
  408. t.expectRightDelim(context)
  409. content, _ = t.itemList(nodeEnd)
  410. } else {
  411. t.unexpected(t.nextNonSpace(), context, "content keyword or closing delimiter")
  412. }
  413. }
  414. return t.newYield(name.pos, t.lex.lineNumber(), name.val, bplist, pipe, content, false)
  415. }
  416. func (t *Template) parseInclude() Node {
  417. var context Expression
  418. name := t.expression("include", "template name")
  419. if t.peekNonSpace().typ != itemRightDelim {
  420. context = t.expression("include", "context")
  421. }
  422. t.expectRightDelim("include invocation")
  423. return t.newInclude(name.Position(), t.lex.lineNumber(), name, context)
  424. }
  425. func (t *Template) parseReturn() Node {
  426. value := t.expression("return", "value")
  427. t.expectRightDelim("return")
  428. return t.newReturn(value.Position(), t.lex.lineNumber(), value)
  429. }
  430. // itemList:
  431. // textOrAction*
  432. // Terminates at any of the given nodes, returned separately.
  433. func (t *Template) itemList(terminatedBy ...NodeType) (list *ListNode, next Node) {
  434. list = t.newList(t.peekNonSpace().pos)
  435. for t.peekNonSpace().typ != itemEOF {
  436. n := t.textOrAction()
  437. for _, terminatorType := range terminatedBy {
  438. if n.Type() == terminatorType {
  439. return list, n
  440. }
  441. }
  442. list.append(n)
  443. }
  444. t.errorf("unexpected EOF")
  445. return
  446. }
  447. // textOrAction:
  448. // text | action
  449. func (t *Template) textOrAction() Node {
  450. switch token := t.nextNonSpace(); token.typ {
  451. case itemText:
  452. return t.newText(token.pos, token.val)
  453. case itemLeftDelim:
  454. return t.action()
  455. default:
  456. t.unexpected(token, "input", "text or action")
  457. }
  458. return nil
  459. }
  460. func (t *Template) action() (n Node) {
  461. switch token := t.nextNonSpace(); token.typ {
  462. case itemInclude:
  463. return t.parseInclude()
  464. case itemBlock:
  465. return t.parseBlock()
  466. case itemEnd:
  467. return t.endControl()
  468. case itemYield:
  469. return t.parseYield()
  470. case itemContent:
  471. return t.contentControl()
  472. case itemIf:
  473. return t.ifControl()
  474. case itemElse:
  475. return t.elseControl()
  476. case itemRange:
  477. return t.rangeControl()
  478. case itemTry:
  479. return t.parseTry()
  480. case itemCatch:
  481. return t.parseCatch()
  482. case itemReturn:
  483. return t.parseReturn()
  484. }
  485. t.backup()
  486. action := t.newAction(t.peek().pos, t.lex.lineNumber())
  487. expr := t.assignmentOrExpression("command")
  488. if expr.Type() == NodeSet {
  489. action.Set = expr.(*SetNode)
  490. expr = nil
  491. if t.expectOneOf(itemSemicolon, itemRightDelim, "command", "semicolon or right delimiter").typ == itemSemicolon {
  492. expr = t.expression("command", "pipeline base expression")
  493. }
  494. }
  495. if expr != nil {
  496. action.Pipe = t.pipeline("command", expr)
  497. }
  498. return action
  499. }
  500. func (t *Template) logicalExpression(context string) (Expression, item) {
  501. left, endtoken := t.comparativeExpression(context)
  502. for endtoken.typ == itemAnd || endtoken.typ == itemOr {
  503. right, rightendtoken := t.comparativeExpression(context)
  504. left, endtoken = t.newLogicalExpr(left.Position(), t.lex.lineNumber(), left, right, endtoken), rightendtoken
  505. }
  506. return left, endtoken
  507. }
  508. func (t *Template) parseExpression(context string) (Expression, item) {
  509. expression, endtoken := t.logicalExpression(context)
  510. if endtoken.typ == itemTernary {
  511. var left, right Expression
  512. left, endtoken = t.parseExpression(context)
  513. if endtoken.typ != itemColon {
  514. t.unexpected(endtoken, "ternary expression", "colon in ternary expression")
  515. }
  516. right, endtoken = t.parseExpression(context)
  517. expression = t.newTernaryExpr(expression.Position(), t.lex.lineNumber(), expression, left, right)
  518. }
  519. return expression, endtoken
  520. }
  521. func (t *Template) comparativeExpression(context string) (Expression, item) {
  522. left, endtoken := t.numericComparativeExpression(context)
  523. for endtoken.typ == itemEquals || endtoken.typ == itemNotEquals {
  524. right, rightendtoken := t.numericComparativeExpression(context)
  525. left, endtoken = t.newComparativeExpr(left.Position(), t.lex.lineNumber(), left, right, endtoken), rightendtoken
  526. }
  527. return left, endtoken
  528. }
  529. func (t *Template) numericComparativeExpression(context string) (Expression, item) {
  530. left, endtoken := t.additiveExpression(context)
  531. for endtoken.typ >= itemGreat && endtoken.typ <= itemLessEquals {
  532. right, rightendtoken := t.additiveExpression(context)
  533. left, endtoken = t.newNumericComparativeExpr(left.Position(), t.lex.lineNumber(), left, right, endtoken), rightendtoken
  534. }
  535. return left, endtoken
  536. }
  537. func (t *Template) additiveExpression(context string) (Expression, item) {
  538. left, endtoken := t.multiplicativeExpression(context)
  539. for endtoken.typ == itemAdd || endtoken.typ == itemMinus {
  540. right, rightendtoken := t.multiplicativeExpression(context)
  541. left, endtoken = t.newAdditiveExpr(left.Position(), t.lex.lineNumber(), left, right, endtoken), rightendtoken
  542. }
  543. return left, endtoken
  544. }
  545. func (t *Template) multiplicativeExpression(context string) (left Expression, endtoken item) {
  546. left, endtoken = t.unaryExpression(context)
  547. for endtoken.typ >= itemMul && endtoken.typ <= itemMod {
  548. right, rightendtoken := t.unaryExpression(context)
  549. left, endtoken = t.newMultiplicativeExpr(left.Position(), t.lex.lineNumber(), left, right, endtoken), rightendtoken
  550. }
  551. return left, endtoken
  552. }
  553. func (t *Template) unaryExpression(context string) (Expression, item) {
  554. next := t.nextNonSpace()
  555. switch next.typ {
  556. case itemNot:
  557. expr, endToken := t.comparativeExpression(context)
  558. return t.newNotExpr(expr.Position(), t.lex.lineNumber(), expr), endToken
  559. case itemMinus, itemAdd:
  560. return t.newAdditiveExpr(next.pos, t.lex.lineNumber(), nil, t.operand("additive expression"), next), t.nextNonSpace()
  561. default:
  562. t.backup()
  563. }
  564. operand := t.operand(context)
  565. return operand, t.nextNonSpace()
  566. }
  567. func (t *Template) assignmentOrExpression(context string) (operand Expression) {
  568. t.peekNonSpace()
  569. line := t.lex.lineNumber()
  570. var right, left []Expression
  571. var isSet bool
  572. var isLet bool
  573. var returned item
  574. operand, returned = t.parseExpression(context)
  575. pos := operand.Position()
  576. if returned.typ == itemComma || returned.typ == itemAssign {
  577. isSet = true
  578. } else {
  579. if operand == nil {
  580. t.unexpected(returned, context, "operand")
  581. }
  582. t.backup()
  583. return operand
  584. }
  585. if isSet {
  586. leftloop:
  587. for {
  588. switch operand.Type() {
  589. case NodeField, NodeChain, NodeIdentifier, NodeUnderscore:
  590. left = append(left, operand)
  591. default:
  592. t.errorf("unexpected node in assign")
  593. }
  594. switch returned.typ {
  595. case itemComma:
  596. operand, returned = t.parseExpression(context)
  597. case itemAssign:
  598. isLet = returned.val == ":="
  599. break leftloop
  600. default:
  601. t.unexpected(returned, "assignment", "comma or assignment")
  602. }
  603. }
  604. if isLet {
  605. for _, operand := range left {
  606. if operand.Type() != NodeIdentifier && operand.Type() != NodeUnderscore {
  607. t.errorf("unexpected node type %s in variable declaration", operand)
  608. }
  609. }
  610. }
  611. for {
  612. operand, returned = t.parseExpression("assignment")
  613. right = append(right, operand)
  614. if returned.typ != itemComma {
  615. t.backup()
  616. break
  617. }
  618. }
  619. var isIndexExprGetLookup bool
  620. if context == "range" {
  621. if len(left) > 2 || len(right) > 1 {
  622. t.errorf("unexpected number of operands in assign on range")
  623. }
  624. } else {
  625. if len(left) != len(right) {
  626. if len(left) == 2 && len(right) == 1 && right[0].Type() == NodeIndexExpr {
  627. isIndexExprGetLookup = true
  628. } else {
  629. t.errorf("unexpected number of operands in assign on range")
  630. }
  631. }
  632. }
  633. operand = t.newSet(pos, line, isLet, isIndexExprGetLookup, left, right)
  634. return
  635. }
  636. return
  637. }
  638. func (t *Template) expression(context, as string) Expression {
  639. expr, tk := t.parseExpression(context)
  640. if expr == nil {
  641. t.unexpected(tk, context, as)
  642. }
  643. t.backup()
  644. return expr
  645. }
  646. func (t *Template) pipeline(context string, baseExprMutate Expression) (pipe *PipeNode) {
  647. pos := t.peekNonSpace().pos
  648. pipe = t.newPipeline(pos, t.lex.lineNumber())
  649. if baseExprMutate == nil {
  650. pipe.errorf("parsing pipeline: first expression cannot be nil")
  651. }
  652. pipe.append(t.command(baseExprMutate))
  653. for {
  654. token := t.expectOneOf(itemPipe, itemRightDelim, "pipeline", "pipe or right delimiter")
  655. if token.typ == itemRightDelim {
  656. break
  657. }
  658. token = t.nextNonSpace()
  659. switch token.typ {
  660. case itemField, itemIdentifier:
  661. t.backup()
  662. pipe.append(t.command(nil))
  663. default:
  664. t.unexpected(token, "pipeline", "field or identifier")
  665. }
  666. }
  667. return
  668. }
  669. func (t *Template) command(baseExpr Expression) *CommandNode {
  670. cmd := t.newCommand(t.peekNonSpace().pos)
  671. if baseExpr == nil {
  672. baseExpr = t.expression("command", "name")
  673. }
  674. if baseExpr.Type() == NodeCallExpr {
  675. call := baseExpr.(*CallExprNode)
  676. cmd.CallExprNode = *call
  677. return cmd
  678. }
  679. cmd.BaseExpr = baseExpr
  680. next := t.nextNonSpace()
  681. switch next.typ {
  682. case itemColon:
  683. cmd.CallArgs = t.parseArguments()
  684. default:
  685. t.backup()
  686. }
  687. if cmd.BaseExpr == nil {
  688. t.errorf("empty command")
  689. }
  690. return cmd
  691. }
  692. // operand:
  693. // term .Field*
  694. // An operand is a space-separated component of a command,
  695. // a term possibly followed by field accesses.
  696. // A nil return means the next item is not an operand.
  697. func (t *Template) operand(context string) Expression {
  698. node := t.term()
  699. if node == nil {
  700. t.unexpected(t.next(), context, "term")
  701. }
  702. RESET:
  703. if t.peek().typ == itemField {
  704. chain := t.newChain(t.peek().pos, node)
  705. for t.peekNonSpace().typ == itemField {
  706. chain.Add(t.next().val)
  707. }
  708. // Compatibility with original API: If the term is of type NodeField
  709. // or NodeVariable, just put more fields on the original.
  710. // Otherwise, keep the Chain node.
  711. // Obvious parsing errors involving literal values are detected here.
  712. // More complex error cases will have to be handled at execution time.
  713. switch node.Type() {
  714. case NodeField:
  715. node = t.newField(chain.Position(), chain.String())
  716. case NodeBool, NodeString, NodeNumber, NodeNil:
  717. t.errorf("unexpected . after term %q", node.String())
  718. default:
  719. node = chain
  720. }
  721. }
  722. nodeTYPE := node.Type()
  723. if nodeTYPE == NodeIdentifier ||
  724. nodeTYPE == NodeCallExpr ||
  725. nodeTYPE == NodeField ||
  726. nodeTYPE == NodeChain ||
  727. nodeTYPE == NodeIndexExpr {
  728. switch t.nextNonSpace().typ {
  729. case itemLeftParen:
  730. callExpr := t.newCallExpr(node.Position(), t.lex.lineNumber(), node)
  731. callExpr.CallArgs = t.parseArguments()
  732. t.expect(itemRightParen, "call expression", "closing parenthesis")
  733. node = callExpr
  734. goto RESET
  735. case itemLeftBrackets:
  736. base := node
  737. var index Expression
  738. var next item
  739. //found colon is slice expression
  740. if t.peekNonSpace().typ != itemColon {
  741. index, next = t.parseExpression("index|slice expression")
  742. } else {
  743. next = t.nextNonSpace()
  744. }
  745. switch next.typ {
  746. case itemColon:
  747. var endIndex Expression
  748. if t.peekNonSpace().typ != itemRightBrackets {
  749. endIndex = t.expression("slice expression", "end indexß")
  750. }
  751. node = t.newSliceExpr(node.Position(), node.line(), base, index, endIndex)
  752. case itemRightBrackets:
  753. node = t.newIndexExpr(node.Position(), node.line(), base, index)
  754. fallthrough
  755. default:
  756. t.backup()
  757. }
  758. t.expect(itemRightBrackets, "index expression", "closing bracket")
  759. goto RESET
  760. default:
  761. t.backup()
  762. }
  763. }
  764. return node
  765. }
  766. func (t *Template) parseArguments() (args CallArgs) {
  767. context := "call expression argument list"
  768. args.Exprs = []Expression{}
  769. loop:
  770. for {
  771. peek := t.peekNonSpace()
  772. if peek.typ == itemRightParen {
  773. break
  774. }
  775. var (
  776. expr Expression
  777. endtoken item
  778. )
  779. expr, endtoken = t.parseExpression(context)
  780. if expr.Type() == NodeUnderscore {
  781. // slot for piped argument
  782. if args.HasPipeSlot {
  783. t.errorf("found two pipe slot markers ('_') for the same function call")
  784. }
  785. args.HasPipeSlot = true
  786. }
  787. args.Exprs = append(args.Exprs, expr)
  788. switch endtoken.typ {
  789. case itemComma:
  790. // continue with closing parens (allowed because of multiline syntax) or next arg
  791. default:
  792. t.backup()
  793. break loop
  794. }
  795. }
  796. return
  797. }
  798. func (t *Template) parseControl(allowElseIf bool, context string) (pos Pos, line int, set *SetNode, expression Expression, list, elseList *ListNode) {
  799. line = t.lex.lineNumber()
  800. expression = t.assignmentOrExpression(context)
  801. pos = expression.Position()
  802. if expression.Type() == NodeSet {
  803. set = expression.(*SetNode)
  804. if context != "range" {
  805. t.expect(itemSemicolon, context, "semicolon between assignment and expression")
  806. expression = t.expression(context, "expression after assignment")
  807. } else {
  808. expression = nil
  809. }
  810. }
  811. t.expectRightDelim(context)
  812. var next Node
  813. list, next = t.itemList(nodeElse, nodeEnd)
  814. if next.Type() == nodeElse {
  815. if allowElseIf && t.peek().typ == itemIf {
  816. // Special case for "else if". If the "else" is followed immediately by an "if",
  817. // the elseControl will have left the "if" token pending. Treat
  818. // {{if a}}_{{else if b}}_{{end}}
  819. // as
  820. // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
  821. // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
  822. // is assumed. This technique works even for long if-else-if chains.
  823. t.next() // Consume the "if" token.
  824. elseList = t.newList(next.Position())
  825. elseList.append(t.ifControl())
  826. // Do not consume the next item - only one {{end}} required.
  827. } else {
  828. elseList, next = t.itemList(nodeEnd)
  829. }
  830. }
  831. return pos, line, set, expression, list, elseList
  832. }
  833. // If:
  834. // {{if expression}} itemList {{end}}
  835. // {{if expression}} itemList {{else}} itemList {{end}}
  836. // If keyword is past.
  837. func (t *Template) ifControl() Node {
  838. return t.newIf(t.parseControl(true, "if"))
  839. }
  840. // Range:
  841. // {{range expression}} itemList {{end}}
  842. // {{range expression}} itemList {{else}} itemList {{end}}
  843. // Range keyword is past.
  844. func (t *Template) rangeControl() Node {
  845. return t.newRange(t.parseControl(false, "range"))
  846. }
  847. // End:
  848. // {{end}}
  849. // End keyword is past.
  850. func (t *Template) endControl() Node {
  851. return t.newEnd(t.expectRightDelim("end").pos)
  852. }
  853. // Content:
  854. // {{content}}
  855. // Content keyword is past.
  856. func (t *Template) contentControl() Node {
  857. return t.newContent(t.expectRightDelim("content").pos)
  858. }
  859. // Else:
  860. // {{else}}
  861. // Else keyword is past.
  862. func (t *Template) elseControl() Node {
  863. // Special case for "else if".
  864. peek := t.peekNonSpace()
  865. if peek.typ == itemIf {
  866. // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
  867. return t.newElse(peek.pos, t.lex.lineNumber())
  868. }
  869. return t.newElse(t.expectRightDelim("else").pos, t.lex.lineNumber())
  870. }
  871. // Try-catch:
  872. // {{try}}
  873. // itemList
  874. // {{catch <ident>}}
  875. // itemList
  876. // {{end}}
  877. // try keyword is past.
  878. func (t *Template) parseTry() *TryNode {
  879. var recov *catchNode
  880. line := t.lex.lineNumber()
  881. pos := t.expectRightDelim("try").pos
  882. list, next := t.itemList(nodeCatch, nodeEnd)
  883. if next.Type() == nodeCatch {
  884. recov = next.(*catchNode)
  885. }
  886. return t.newTry(pos, line, list, recov)
  887. }
  888. // catch:
  889. // {{catch <ident>}}
  890. // itemList
  891. // {{end}}
  892. // catch keyword is past.
  893. func (t *Template) parseCatch() *catchNode {
  894. line := t.lex.lineNumber()
  895. var errVar *IdentifierNode
  896. peek := t.peekNonSpace()
  897. if peek.typ != itemRightDelim {
  898. _errVar := t.term()
  899. if typ := _errVar.Type(); typ != NodeIdentifier {
  900. t.errorf("unexpected node type '%s' in catch", typ)
  901. }
  902. errVar = _errVar.(*IdentifierNode)
  903. }
  904. t.expectRightDelim("catch")
  905. list, _ := t.itemList(nodeEnd)
  906. return t.newCatch(peek.pos, line, errVar, list)
  907. }
  908. // term:
  909. // literal (number, string, nil, boolean)
  910. // function (identifier)
  911. // .
  912. // .Field
  913. // variable
  914. // '(' expression ')'
  915. // A term is a simple "expression".
  916. // A nil return means the next item is not a term.
  917. func (t *Template) term() Node {
  918. switch token := t.nextNonSpace(); token.typ {
  919. case itemError:
  920. t.errorf("%s", token.val)
  921. case itemIdentifier:
  922. return t.newIdentifier(token.val, token.pos, t.lex.lineNumber())
  923. case itemUnderscore:
  924. return t.newUnderscore(token.pos, t.lex.lineNumber())
  925. case itemNil:
  926. return t.newNil(token.pos)
  927. case itemField:
  928. return t.newField(token.pos, token.val)
  929. case itemBool:
  930. return t.newBool(token.pos, token.val == "true")
  931. case itemCharConstant, itemComplex, itemNumber:
  932. number, err := t.newNumber(token.pos, token.val, token.typ)
  933. if err != nil {
  934. t.error(err)
  935. }
  936. return number
  937. case itemLeftParen:
  938. pipe := t.expression("parenthesized expression", "expression")
  939. if token := t.next(); token.typ != itemRightParen {
  940. t.unexpected(token, "parenthesized expression", "closing parenthesis")
  941. }
  942. return pipe
  943. case itemString, itemRawString:
  944. s, err := unquote(token.val)
  945. if err != nil {
  946. t.error(err)
  947. }
  948. return t.newString(token.pos, token.val, s)
  949. }
  950. t.backup()
  951. return nil
  952. }