node.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  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. )
  19. var textFormat = "%s" //Changed to "%q" in tests for better error messages.
  20. type Node interface {
  21. Type() NodeType
  22. String() string
  23. Position() Pos
  24. line() int
  25. error(error)
  26. errorf(string, ...interface{})
  27. }
  28. type Expression interface {
  29. Node
  30. }
  31. // Pos represents a byte position in the original input text from which
  32. // this template was parsed.
  33. type Pos int
  34. func (p Pos) Position() Pos {
  35. return p
  36. }
  37. // NodeType identifies the type of a parse tree node.
  38. type NodeType int
  39. type NodeBase struct {
  40. TemplateName string
  41. Line int
  42. NodeType
  43. Pos
  44. }
  45. func (node *NodeBase) line() int {
  46. return node.Line
  47. }
  48. func (node *NodeBase) error(err error) {
  49. node.errorf("%s", err)
  50. }
  51. func (node *NodeBase) errorf(format string, v ...interface{}) {
  52. panic(fmt.Errorf("Jet Runtime Error(%q:%d): %s", node.TemplateName, node.Line, fmt.Sprintf(format, v...)))
  53. }
  54. // Type returns itself and provides an easy default implementation
  55. // for embedding in a Node. Embedded in all non-trivial Nodes.
  56. func (t NodeType) Type() NodeType {
  57. return t
  58. }
  59. const (
  60. NodeText NodeType = iota //Plain text.
  61. NodeAction //A non-control action such as a field evaluation.
  62. NodeChain //A sequence of field accesses.
  63. NodeCommand //An element of a pipeline.
  64. nodeElse //An else action. Not added to tree.
  65. nodeEnd //An end action. Not added to tree.
  66. NodeField //A field or method name.
  67. NodeIdentifier //An identifier; always a function name.
  68. NodeIf //An if action.
  69. NodeList //A list of Nodes.
  70. NodePipe //A pipeline of commands.
  71. NodeRange //A range action.
  72. nodeContent
  73. //NodeWith //A with action.
  74. NodeBlock
  75. NodeInclude
  76. NodeYield
  77. NodeSet
  78. beginExpressions
  79. NodeString //A string constant.
  80. NodeNil //An untyped nil constant.
  81. NodeNumber //A numerical constant.
  82. NodeBool //A boolean constant.
  83. NodeAdditiveExpr
  84. NodeMultiplicativeExpr
  85. NodeComparativeExpr
  86. NodeNumericComparativeExpr
  87. NodeLogicalExpr
  88. NodeCallExpr
  89. NodeNotExpr
  90. NodeTernaryExpr
  91. NodeIndexExpr
  92. NodeSliceExpr
  93. endExpressions
  94. )
  95. // Nodes.
  96. // ListNode holds a sequence of nodes.
  97. type ListNode struct {
  98. NodeBase
  99. Nodes []Node //The element nodes in lexical order.
  100. }
  101. func (l *ListNode) append(n Node) {
  102. l.Nodes = append(l.Nodes, n)
  103. }
  104. func (l *ListNode) String() string {
  105. b := new(bytes.Buffer)
  106. for _, n := range l.Nodes {
  107. fmt.Fprint(b, n)
  108. }
  109. return b.String()
  110. }
  111. // TextNode holds plain text.
  112. type TextNode struct {
  113. NodeBase
  114. Text []byte
  115. }
  116. func (t *TextNode) String() string {
  117. return fmt.Sprintf(textFormat, t.Text)
  118. }
  119. // PipeNode holds a pipeline with optional declaration
  120. type PipeNode struct {
  121. NodeBase //The line number in the input. Deprecated: Kept for compatibility.
  122. Cmds []*CommandNode //The commands in lexical order.
  123. }
  124. func (p *PipeNode) append(command *CommandNode) {
  125. p.Cmds = append(p.Cmds, command)
  126. }
  127. func (p *PipeNode) String() string {
  128. s := ""
  129. for i, c := range p.Cmds {
  130. if i > 0 {
  131. s += " | "
  132. }
  133. s += c.String()
  134. }
  135. return s
  136. }
  137. // ActionNode holds an action (something bounded by delimiters).
  138. // Control actions have their own nodes; ActionNode represents simple
  139. // ones such as field evaluations and parenthesized pipelines.
  140. type ActionNode struct {
  141. NodeBase
  142. Set *SetNode
  143. Pipe *PipeNode
  144. }
  145. func (a *ActionNode) String() string {
  146. if a.Set != nil {
  147. if a.Pipe == nil {
  148. return fmt.Sprintf("{{%s}}", a.Set)
  149. }
  150. return fmt.Sprintf("{{%s;%s}}", a.Set, a.Pipe)
  151. }
  152. return fmt.Sprintf("{{%s}}", a.Pipe)
  153. }
  154. // CommandNode holds a command (a pipeline inside an evaluating action).
  155. type CommandNode struct {
  156. NodeBase
  157. Call bool
  158. BaseExpr Expression
  159. Args []Expression
  160. }
  161. func (c *CommandNode) append(arg Node) {
  162. c.Args = append(c.Args, arg)
  163. }
  164. func (c *CommandNode) String() string {
  165. s := c.BaseExpr.String()
  166. if c.Call {
  167. s += ":"
  168. }
  169. for i, arg := range c.Args {
  170. if i > 0 {
  171. s += ", "
  172. }
  173. if _, ok := arg.(*PipeNode); ok {
  174. s += "(" + arg.String() + ")"
  175. } else {
  176. s += arg.String()
  177. }
  178. }
  179. return s
  180. }
  181. // IdentifierNode holds an identifier.
  182. type IdentifierNode struct {
  183. NodeBase
  184. Ident string //The identifier's name.
  185. }
  186. func (i *IdentifierNode) String() string {
  187. return i.Ident
  188. }
  189. // NilNode holds the special identifier 'nil' representing an untyped nil constant.
  190. type NilNode struct {
  191. NodeBase
  192. }
  193. func (n *NilNode) String() string {
  194. return "nil"
  195. }
  196. // FieldNode holds a field (identifier starting with '.').
  197. // The names may be chained ('.x.y').
  198. // The period is dropped from each ident.
  199. type FieldNode struct {
  200. NodeBase
  201. Ident []string //The identifiers in lexical order.
  202. }
  203. func (f *FieldNode) String() string {
  204. s := ""
  205. for _, id := range f.Ident {
  206. s += "." + id
  207. }
  208. return s
  209. }
  210. // ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
  211. // The names may be chained ('.x.y').
  212. // The periods are dropped from each ident.
  213. type ChainNode struct {
  214. NodeBase
  215. Node Node
  216. Field []string //The identifiers in lexical order.
  217. }
  218. // Add adds the named field (which should start with a period) to the end of the chain.
  219. func (c *ChainNode) Add(field string) {
  220. if len(field) == 0 || field[0] != '.' {
  221. panic("no dot in field")
  222. }
  223. field = field[1:] //Remove leading dot.
  224. if field == "" {
  225. panic("empty field")
  226. }
  227. c.Field = append(c.Field, field)
  228. }
  229. func (c *ChainNode) String() string {
  230. s := c.Node.String()
  231. if _, ok := c.Node.(*PipeNode); ok {
  232. s = "(" + s + ")"
  233. }
  234. for _, field := range c.Field {
  235. s += "." + field
  236. }
  237. return s
  238. }
  239. // BoolNode holds a boolean constant.
  240. type BoolNode struct {
  241. NodeBase
  242. True bool //The value of the boolean constant.
  243. }
  244. func (b *BoolNode) String() string {
  245. if b.True {
  246. return "true"
  247. }
  248. return "false"
  249. }
  250. // NumberNode holds a number: signed or unsigned integer, float, or complex.
  251. // The value is parsed and stored under all the types that can represent the value.
  252. // This simulates in a small amount of code the behavior of Go's ideal constants.
  253. type NumberNode struct {
  254. NodeBase
  255. IsInt bool //Number has an integral value.
  256. IsUint bool //Number has an unsigned integral value.
  257. IsFloat bool //Number has a floating-point value.
  258. IsComplex bool //Number is complex.
  259. Int64 int64 //The signed integer value.
  260. Uint64 uint64 //The unsigned integer value.
  261. Float64 float64 //The floating-point value.
  262. Complex128 complex128 //The complex value.
  263. Text string //The original textual representation from the input.
  264. }
  265. // simplifyComplex pulls out any other types that are represented by the complex number.
  266. // These all require that the imaginary part be zero.
  267. func (n *NumberNode) simplifyComplex() {
  268. n.IsFloat = imag(n.Complex128) == 0
  269. if n.IsFloat {
  270. n.Float64 = real(n.Complex128)
  271. n.IsInt = float64(int64(n.Float64)) == n.Float64
  272. if n.IsInt {
  273. n.Int64 = int64(n.Float64)
  274. }
  275. n.IsUint = float64(uint64(n.Float64)) == n.Float64
  276. if n.IsUint {
  277. n.Uint64 = uint64(n.Float64)
  278. }
  279. }
  280. }
  281. func (n *NumberNode) String() string {
  282. return n.Text
  283. }
  284. // StringNode holds a string constant. The value has been "unquoted".
  285. type StringNode struct {
  286. NodeBase
  287. Quoted string //The original text of the string, with quotes.
  288. Text string //The string, after quote processing.
  289. }
  290. func (s *StringNode) String() string {
  291. return s.Quoted
  292. }
  293. // endNode represents an {{end}} action.
  294. // It does not appear in the final parse tree.
  295. type endNode struct {
  296. NodeBase
  297. }
  298. func (e *endNode) String() string {
  299. return "{{end}}"
  300. }
  301. // endNode represents an {{end}} action.
  302. // It does not appear in the final parse tree.
  303. type contentNode struct {
  304. NodeBase
  305. }
  306. func (e *contentNode) String() string {
  307. return "{{content}}"
  308. }
  309. // elseNode represents an {{else}} action. Does not appear in the final tree.
  310. type elseNode struct {
  311. NodeBase //The line number in the input. Deprecated: Kept for compatibility.
  312. }
  313. func (e *elseNode) String() string {
  314. return "{{else}}"
  315. }
  316. // SetNode represents a set action, ident( ',' ident)* '=' expression ( ',' expression )*
  317. type SetNode struct {
  318. NodeBase
  319. Let bool
  320. IndexExprGetLookup bool
  321. Left []Expression
  322. Right []Expression
  323. }
  324. func (set *SetNode) String() string {
  325. var s = ""
  326. for i, v := range set.Left {
  327. if i > 0 {
  328. s += ", "
  329. }
  330. s += v.String()
  331. }
  332. if set.Let {
  333. s += ":="
  334. } else {
  335. s += "="
  336. }
  337. for i, v := range set.Right {
  338. if i > 0 {
  339. s += ", "
  340. }
  341. s += v.String()
  342. }
  343. return s
  344. }
  345. // BranchNode is the common representation of if, range, and with.
  346. type BranchNode struct {
  347. NodeBase
  348. Set *SetNode
  349. Expression Expression
  350. List *ListNode
  351. ElseList *ListNode
  352. }
  353. func (b *BranchNode) String() string {
  354. if b.NodeType == NodeRange {
  355. s := ""
  356. if b.Set != nil {
  357. s = b.Set.String()
  358. } else {
  359. s = b.Expression.String()
  360. }
  361. if b.ElseList != nil {
  362. return fmt.Sprintf("{{range %s}}%s{{else}}%s{{end}}", s, b.List, b.ElseList)
  363. }
  364. return fmt.Sprintf("{{range %s}}%s{{end}}", s, b.List)
  365. } else {
  366. s := ""
  367. if b.Set != nil {
  368. s = b.Set.String() + ";"
  369. }
  370. if b.ElseList != nil {
  371. return fmt.Sprintf("{{if %s%s}}%s{{else}}%s{{end}}", s, b.Expression, b.List, b.ElseList)
  372. }
  373. return fmt.Sprintf("{{if %s%s}}%s{{end}}", s, b.Expression, b.List)
  374. }
  375. }
  376. // IfNode represents an {{if}} action and its commands.
  377. type IfNode struct {
  378. BranchNode
  379. }
  380. // RangeNode represents a {{range}} action and its commands.
  381. type RangeNode struct {
  382. BranchNode
  383. }
  384. type BlockParameter struct {
  385. Identifier string
  386. Expression Expression
  387. }
  388. type BlockParameterList struct {
  389. NodeBase
  390. List []BlockParameter
  391. }
  392. func (bplist *BlockParameterList) Param(name string) (Expression, int) {
  393. for i := 0; i < len(bplist.List); i++ {
  394. param := &bplist.List[i]
  395. if param.Identifier == name {
  396. return param.Expression, i
  397. }
  398. }
  399. return nil, -1
  400. }
  401. func (bplist *BlockParameterList) String() (str string) {
  402. buff := bytes.NewBuffer(nil)
  403. for _, bp := range bplist.List {
  404. if bp.Identifier == "" {
  405. fmt.Fprintf(buff, "%s,", bp.Expression)
  406. } else {
  407. if bp.Expression == nil {
  408. fmt.Fprintf(buff, "%s,", bp.Identifier)
  409. } else {
  410. fmt.Fprintf(buff, "%s=%s,", bp.Identifier, bp.Expression)
  411. }
  412. }
  413. }
  414. if buff.Len() > 0 {
  415. str = buff.String()[0 : buff.Len()-1]
  416. }
  417. return
  418. }
  419. // BlockNode represents a {{block }} action.
  420. type BlockNode struct {
  421. NodeBase //The line number in the input. Deprecated: Kept for compatibility.
  422. Name string //The name of the template (unquoted).
  423. Parameters *BlockParameterList
  424. Expression Expression //The command to evaluate as dot for the template.
  425. List *ListNode
  426. Content *ListNode
  427. }
  428. func (t *BlockNode) String() string {
  429. if t.Content != nil {
  430. if t.Expression == nil {
  431. return fmt.Sprintf("{{block %s(%s)}}%s{{content}}%s{{end}}", t.Name, t.Parameters, t.List, t.Content)
  432. }
  433. return fmt.Sprintf("{{block %s(%s) %s}}%s{{content}}%s{{end}}", t.Name, t.Parameters, t.Expression, t.List, t.Content)
  434. }
  435. if t.Expression == nil {
  436. return fmt.Sprintf("{{block %s(%s)}}%s{{end}}", t.Name, t.Parameters, t.List)
  437. }
  438. return fmt.Sprintf("{{block %s(%s) %s}}%s{{end}}", t.Name, t.Parameters, t.Expression, t.List)
  439. }
  440. // YieldNode represents a {{yield}} action
  441. type YieldNode struct {
  442. NodeBase //The line number in the input. Deprecated: Kept for compatibility.
  443. Name string //The name of the template (unquoted).
  444. Parameters *BlockParameterList
  445. Expression Expression //The command to evaluate as dot for the template.
  446. Content *ListNode
  447. IsContent bool
  448. }
  449. func (t *YieldNode) String() string {
  450. if t.IsContent {
  451. if t.Expression == nil {
  452. return "{{yield content}}"
  453. }
  454. return fmt.Sprintf("{{yield content %s}}", t.Expression)
  455. }
  456. if t.Content != nil {
  457. if t.Expression == nil {
  458. return fmt.Sprintf("{{yield %s(%s) content}}%s{{end}}", t.Name, t.Parameters, t.Content)
  459. }
  460. return fmt.Sprintf("{{yield %s(%s) %s content}}%s{{end}}", t.Name, t.Parameters, t.Expression, t.Content)
  461. }
  462. if t.Expression == nil {
  463. return fmt.Sprintf("{{yield %s(%s)}}", t.Name, t.Parameters)
  464. }
  465. return fmt.Sprintf("{{yield %s(%s) %s}}", t.Name, t.Parameters, t.Expression)
  466. }
  467. // IncludeNode represents a {{include }} action.
  468. type IncludeNode struct {
  469. NodeBase
  470. Name Expression
  471. Expression Expression
  472. }
  473. func (t *IncludeNode) String() string {
  474. if t.Expression == nil {
  475. return fmt.Sprintf("{{include %s}}", t.Name)
  476. }
  477. return fmt.Sprintf("{{include %s %s}}", t.Name, t.Expression)
  478. }
  479. type binaryExprNode struct {
  480. NodeBase
  481. Operator item
  482. Left, Right Expression
  483. }
  484. func (node *binaryExprNode) String() string {
  485. return fmt.Sprintf("%s %s %s", node.Left, node.Operator.val, node.Right)
  486. }
  487. // AdditiveExprNode represents an add or subtract expression
  488. // ex: expression ( '+' | '-' ) expression
  489. type AdditiveExprNode struct {
  490. binaryExprNode
  491. }
  492. // MultiplicativeExprNode represents a multiplication, division, or module expression
  493. // ex: expression ( '*' | '/' | '%' ) expression
  494. type MultiplicativeExprNode struct {
  495. binaryExprNode
  496. }
  497. // LogicalExprNode represents a boolean expression, 'and' or 'or'
  498. // ex: expression ( '&&' | '||' ) expression
  499. type LogicalExprNode struct {
  500. binaryExprNode
  501. }
  502. // ComparativeExprNode represents a comparative expression
  503. // ex: expression ( '==' | '!=' ) expression
  504. type ComparativeExprNode struct {
  505. binaryExprNode
  506. }
  507. // NumericComparativeExprNode represents a numeric comparative expression
  508. // ex: expression ( '<' | '>' | '<=' | '>=' ) expression
  509. type NumericComparativeExprNode struct {
  510. binaryExprNode
  511. }
  512. // NotExprNode represents a negate expression
  513. // ex: '!' expression
  514. type NotExprNode struct {
  515. NodeBase
  516. Expr Expression
  517. }
  518. func (s *NotExprNode) String() string {
  519. return fmt.Sprintf("!%s", s.Expr)
  520. }
  521. // CallExprNode represents a call expression
  522. // ex: expression '(' (expression (',' expression)* )? ')'
  523. type CallExprNode struct {
  524. NodeBase
  525. BaseExpr Expression
  526. Args []Expression
  527. }
  528. func (s *CallExprNode) String() string {
  529. arguments := ""
  530. for i, expr := range s.Args {
  531. if i > 0 {
  532. arguments += ", "
  533. }
  534. arguments += expr.String()
  535. }
  536. return fmt.Sprintf("%s(%s)", s.BaseExpr, arguments)
  537. }
  538. // TernaryExprNod represents a ternary expression,
  539. // ex: expression '?' expression ':' expression
  540. type TernaryExprNode struct {
  541. NodeBase
  542. Boolean, Left, Right Expression
  543. }
  544. func (s *TernaryExprNode) String() string {
  545. return fmt.Sprintf("%s?%s:%s", s.Boolean, s.Left, s.Right)
  546. }
  547. type IndexExprNode struct {
  548. NodeBase
  549. Base Expression
  550. Index Expression
  551. }
  552. func (s *IndexExprNode) String() string {
  553. return fmt.Sprintf("%s[%s]", s.Base, s.Index)
  554. }
  555. type SliceExprNode struct {
  556. NodeBase
  557. Base Expression
  558. Index Expression
  559. EndIndex Expression
  560. }
  561. func (s *SliceExprNode) String() string {
  562. var index_string, len_string string
  563. if s.Index != nil {
  564. index_string = s.Index.String()
  565. }
  566. if s.EndIndex != nil {
  567. len_string = s.EndIndex.String()
  568. }
  569. return fmt.Sprintf("%s[%s:%s]", s.Base, index_string, len_string)
  570. }