parser.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. // Package parser provides a handlebars syntax analyser. It consumes the tokens provided by the lexer to build an AST.
  2. package parser
  3. import (
  4. "fmt"
  5. "regexp"
  6. "runtime"
  7. "strconv"
  8. "github.com/aymerick/raymond/ast"
  9. "github.com/aymerick/raymond/lexer"
  10. )
  11. // References:
  12. // - https://github.com/wycats/handlebars.js/blob/master/src/handlebars.yy
  13. // - https://github.com/golang/go/blob/master/src/text/template/parse/parse.go
  14. // parser is a syntax analyzer.
  15. type parser struct {
  16. // Lexer
  17. lex *lexer.Lexer
  18. // Root node
  19. root ast.Node
  20. // Tokens parsed but not consumed yet
  21. tokens []*lexer.Token
  22. // All tokens have been retreieved from lexer
  23. lexOver bool
  24. }
  25. var (
  26. rOpenComment = regexp.MustCompile(`^\{\{~?!-?-?`)
  27. rCloseComment = regexp.MustCompile(`-?-?~?\}\}$`)
  28. rOpenAmp = regexp.MustCompile(`^\{\{~?&`)
  29. )
  30. // new instanciates a new parser
  31. func new(input string) *parser {
  32. return &parser{
  33. lex: lexer.Scan(input),
  34. }
  35. }
  36. // Parse analyzes given input and returns the AST root node.
  37. func Parse(input string) (result *ast.Program, err error) {
  38. // recover error
  39. defer errRecover(&err)
  40. parser := new(input)
  41. // parse
  42. result = parser.parseProgram()
  43. // check last token
  44. token := parser.shift()
  45. if token.Kind != lexer.TokenEOF {
  46. // Parsing ended before EOF
  47. errToken(token, "Syntax error")
  48. }
  49. // fix whitespaces
  50. processWhitespaces(result)
  51. // named returned values
  52. return
  53. }
  54. // errRecover recovers parsing panic
  55. func errRecover(errp *error) {
  56. e := recover()
  57. if e != nil {
  58. switch err := e.(type) {
  59. case runtime.Error:
  60. panic(e)
  61. case error:
  62. *errp = err
  63. default:
  64. panic(e)
  65. }
  66. }
  67. }
  68. // errPanic panics
  69. func errPanic(err error, line int) {
  70. panic(fmt.Errorf("Parse error on line %d:\n%s", line, err))
  71. }
  72. // errNode panics with given node infos
  73. func errNode(node ast.Node, msg string) {
  74. errPanic(fmt.Errorf("%s\nNode: %s", msg, node), node.Location().Line)
  75. }
  76. // errNode panics with given Token infos
  77. func errToken(tok *lexer.Token, msg string) {
  78. errPanic(fmt.Errorf("%s\nToken: %s", msg, tok), tok.Line)
  79. }
  80. // errNode panics because of an unexpected Token kind
  81. func errExpected(expect lexer.TokenKind, tok *lexer.Token) {
  82. errPanic(fmt.Errorf("Expecting %s, got: '%s'", expect, tok), tok.Line)
  83. }
  84. // program : statement*
  85. func (p *parser) parseProgram() *ast.Program {
  86. result := ast.NewProgram(p.next().Pos, p.next().Line)
  87. for p.isStatement() {
  88. result.AddStatement(p.parseStatement())
  89. }
  90. return result
  91. }
  92. // statement : mustache | block | rawBlock | partial | content | COMMENT
  93. func (p *parser) parseStatement() ast.Node {
  94. var result ast.Node
  95. tok := p.next()
  96. switch tok.Kind {
  97. case lexer.TokenOpen, lexer.TokenOpenUnescaped:
  98. // mustache
  99. result = p.parseMustache()
  100. case lexer.TokenOpenBlock:
  101. // block
  102. result = p.parseBlock()
  103. case lexer.TokenOpenInverse:
  104. // block
  105. result = p.parseInverse()
  106. case lexer.TokenOpenRawBlock:
  107. // rawBlock
  108. result = p.parseRawBlock()
  109. case lexer.TokenOpenPartial:
  110. // partial
  111. result = p.parsePartial()
  112. case lexer.TokenContent:
  113. // content
  114. result = p.parseContent()
  115. case lexer.TokenComment:
  116. // COMMENT
  117. result = p.parseComment()
  118. }
  119. return result
  120. }
  121. // isStatement returns true if next token starts a statement
  122. func (p *parser) isStatement() bool {
  123. if !p.have(1) {
  124. return false
  125. }
  126. switch p.next().Kind {
  127. case lexer.TokenOpen, lexer.TokenOpenUnescaped, lexer.TokenOpenBlock,
  128. lexer.TokenOpenInverse, lexer.TokenOpenRawBlock, lexer.TokenOpenPartial,
  129. lexer.TokenContent, lexer.TokenComment:
  130. return true
  131. }
  132. return false
  133. }
  134. // content : CONTENT
  135. func (p *parser) parseContent() *ast.ContentStatement {
  136. // CONTENT
  137. tok := p.shift()
  138. if tok.Kind != lexer.TokenContent {
  139. // @todo This check can be removed if content is optional in a raw block
  140. errExpected(lexer.TokenContent, tok)
  141. }
  142. return ast.NewContentStatement(tok.Pos, tok.Line, tok.Val)
  143. }
  144. // COMMENT
  145. func (p *parser) parseComment() *ast.CommentStatement {
  146. // COMMENT
  147. tok := p.shift()
  148. value := rOpenComment.ReplaceAllString(tok.Val, "")
  149. value = rCloseComment.ReplaceAllString(value, "")
  150. result := ast.NewCommentStatement(tok.Pos, tok.Line, value)
  151. result.Strip = ast.NewStripForStr(tok.Val)
  152. return result
  153. }
  154. // param* hash?
  155. func (p *parser) parseExpressionParamsHash() ([]ast.Node, *ast.Hash) {
  156. var params []ast.Node
  157. var hash *ast.Hash
  158. // params*
  159. if p.isParam() {
  160. params = p.parseParams()
  161. }
  162. // hash?
  163. if p.isHashSegment() {
  164. hash = p.parseHash()
  165. }
  166. return params, hash
  167. }
  168. // helperName param* hash?
  169. func (p *parser) parseExpression(tok *lexer.Token) *ast.Expression {
  170. result := ast.NewExpression(tok.Pos, tok.Line)
  171. // helperName
  172. result.Path = p.parseHelperName()
  173. // param* hash?
  174. result.Params, result.Hash = p.parseExpressionParamsHash()
  175. return result
  176. }
  177. // rawBlock : openRawBlock content endRawBlock
  178. // openRawBlock : OPEN_RAW_BLOCK helperName param* hash? CLOSE_RAW_BLOCK
  179. // endRawBlock : OPEN_END_RAW_BLOCK helperName CLOSE_RAW_BLOCK
  180. func (p *parser) parseRawBlock() *ast.BlockStatement {
  181. // OPEN_RAW_BLOCK
  182. tok := p.shift()
  183. result := ast.NewBlockStatement(tok.Pos, tok.Line)
  184. // helperName param* hash?
  185. result.Expression = p.parseExpression(tok)
  186. openName := result.Expression.Canonical()
  187. // CLOSE_RAW_BLOCK
  188. tok = p.shift()
  189. if tok.Kind != lexer.TokenCloseRawBlock {
  190. errExpected(lexer.TokenCloseRawBlock, tok)
  191. }
  192. // content
  193. // @todo Is content mandatory in a raw block ?
  194. content := p.parseContent()
  195. program := ast.NewProgram(tok.Pos, tok.Line)
  196. program.AddStatement(content)
  197. result.Program = program
  198. // OPEN_END_RAW_BLOCK
  199. tok = p.shift()
  200. if tok.Kind != lexer.TokenOpenEndRawBlock {
  201. // should never happen as it is caught by lexer
  202. errExpected(lexer.TokenOpenEndRawBlock, tok)
  203. }
  204. // helperName
  205. endID := p.parseHelperName()
  206. closeName, ok := ast.HelperNameStr(endID)
  207. if !ok {
  208. errNode(endID, "Erroneous closing expression")
  209. }
  210. if openName != closeName {
  211. errNode(endID, fmt.Sprintf("%s doesn't match %s", openName, closeName))
  212. }
  213. // CLOSE_RAW_BLOCK
  214. tok = p.shift()
  215. if tok.Kind != lexer.TokenCloseRawBlock {
  216. errExpected(lexer.TokenCloseRawBlock, tok)
  217. }
  218. return result
  219. }
  220. // block : openBlock program inverseChain? closeBlock
  221. func (p *parser) parseBlock() *ast.BlockStatement {
  222. // openBlock
  223. result, blockParams := p.parseOpenBlock()
  224. // program
  225. program := p.parseProgram()
  226. program.BlockParams = blockParams
  227. result.Program = program
  228. // inverseChain?
  229. if p.isInverseChain() {
  230. result.Inverse = p.parseInverseChain()
  231. }
  232. // closeBlock
  233. p.parseCloseBlock(result)
  234. setBlockInverseStrip(result)
  235. return result
  236. }
  237. // setBlockInverseStrip is called when parsing `block` (openBlock | openInverse) and `inverseChain`
  238. //
  239. // TODO: This was totally cargo culted ! CHECK THAT !
  240. //
  241. // cf. prepareBlock() in:
  242. // https://github.com/wycats/handlebars.js/blob/master/lib/handlebars/compiler/helper.js
  243. func setBlockInverseStrip(block *ast.BlockStatement) {
  244. if block.Inverse == nil {
  245. return
  246. }
  247. if block.Inverse.Chained {
  248. b, _ := block.Inverse.Body[0].(*ast.BlockStatement)
  249. b.CloseStrip = block.CloseStrip
  250. }
  251. block.InverseStrip = block.Inverse.Strip
  252. }
  253. // block : openInverse program inverseAndProgram? closeBlock
  254. func (p *parser) parseInverse() *ast.BlockStatement {
  255. // openInverse
  256. result, blockParams := p.parseOpenBlock()
  257. // program
  258. program := p.parseProgram()
  259. program.BlockParams = blockParams
  260. result.Inverse = program
  261. // inverseAndProgram?
  262. if p.isInverse() {
  263. result.Program = p.parseInverseAndProgram()
  264. }
  265. // closeBlock
  266. p.parseCloseBlock(result)
  267. setBlockInverseStrip(result)
  268. return result
  269. }
  270. // helperName param* hash? blockParams?
  271. func (p *parser) parseOpenBlockExpression(tok *lexer.Token) (*ast.BlockStatement, []string) {
  272. var blockParams []string
  273. result := ast.NewBlockStatement(tok.Pos, tok.Line)
  274. // helperName param* hash?
  275. result.Expression = p.parseExpression(tok)
  276. // blockParams?
  277. if p.isBlockParams() {
  278. blockParams = p.parseBlockParams()
  279. }
  280. // named returned values
  281. return result, blockParams
  282. }
  283. // inverseChain : openInverseChain program inverseChain?
  284. // | inverseAndProgram
  285. func (p *parser) parseInverseChain() *ast.Program {
  286. if p.isInverse() {
  287. // inverseAndProgram
  288. return p.parseInverseAndProgram()
  289. }
  290. result := ast.NewProgram(p.next().Pos, p.next().Line)
  291. // openInverseChain
  292. block, blockParams := p.parseOpenBlock()
  293. // program
  294. program := p.parseProgram()
  295. program.BlockParams = blockParams
  296. block.Program = program
  297. // inverseChain?
  298. if p.isInverseChain() {
  299. block.Inverse = p.parseInverseChain()
  300. }
  301. setBlockInverseStrip(block)
  302. result.Chained = true
  303. result.AddStatement(block)
  304. return result
  305. }
  306. // Returns true if current token starts an inverse chain
  307. func (p *parser) isInverseChain() bool {
  308. return p.isOpenInverseChain() || p.isInverse()
  309. }
  310. // inverseAndProgram : INVERSE program
  311. func (p *parser) parseInverseAndProgram() *ast.Program {
  312. // INVERSE
  313. tok := p.shift()
  314. // program
  315. result := p.parseProgram()
  316. result.Strip = ast.NewStripForStr(tok.Val)
  317. return result
  318. }
  319. // openBlock : OPEN_BLOCK helperName param* hash? blockParams? CLOSE
  320. // openInverse : OPEN_INVERSE helperName param* hash? blockParams? CLOSE
  321. // openInverseChain: OPEN_INVERSE_CHAIN helperName param* hash? blockParams? CLOSE
  322. func (p *parser) parseOpenBlock() (*ast.BlockStatement, []string) {
  323. // OPEN_BLOCK | OPEN_INVERSE | OPEN_INVERSE_CHAIN
  324. tok := p.shift()
  325. // helperName param* hash? blockParams?
  326. result, blockParams := p.parseOpenBlockExpression(tok)
  327. // CLOSE
  328. tokClose := p.shift()
  329. if tokClose.Kind != lexer.TokenClose {
  330. errExpected(lexer.TokenClose, tokClose)
  331. }
  332. result.OpenStrip = ast.NewStrip(tok.Val, tokClose.Val)
  333. // named returned values
  334. return result, blockParams
  335. }
  336. // closeBlock : OPEN_ENDBLOCK helperName CLOSE
  337. func (p *parser) parseCloseBlock(block *ast.BlockStatement) {
  338. // OPEN_ENDBLOCK
  339. tok := p.shift()
  340. if tok.Kind != lexer.TokenOpenEndBlock {
  341. errExpected(lexer.TokenOpenEndBlock, tok)
  342. }
  343. // helperName
  344. endID := p.parseHelperName()
  345. closeName, ok := ast.HelperNameStr(endID)
  346. if !ok {
  347. errNode(endID, "Erroneous closing expression")
  348. }
  349. openName := block.Expression.Canonical()
  350. if openName != closeName {
  351. errNode(endID, fmt.Sprintf("%s doesn't match %s", openName, closeName))
  352. }
  353. // CLOSE
  354. tokClose := p.shift()
  355. if tokClose.Kind != lexer.TokenClose {
  356. errExpected(lexer.TokenClose, tokClose)
  357. }
  358. block.CloseStrip = ast.NewStrip(tok.Val, tokClose.Val)
  359. }
  360. // mustache : OPEN helperName param* hash? CLOSE
  361. // | OPEN_UNESCAPED helperName param* hash? CLOSE_UNESCAPED
  362. func (p *parser) parseMustache() *ast.MustacheStatement {
  363. // OPEN | OPEN_UNESCAPED
  364. tok := p.shift()
  365. closeToken := lexer.TokenClose
  366. if tok.Kind == lexer.TokenOpenUnescaped {
  367. closeToken = lexer.TokenCloseUnescaped
  368. }
  369. unescaped := false
  370. if (tok.Kind == lexer.TokenOpenUnescaped) || (rOpenAmp.MatchString(tok.Val)) {
  371. unescaped = true
  372. }
  373. result := ast.NewMustacheStatement(tok.Pos, tok.Line, unescaped)
  374. // helperName param* hash?
  375. result.Expression = p.parseExpression(tok)
  376. // CLOSE | CLOSE_UNESCAPED
  377. tokClose := p.shift()
  378. if tokClose.Kind != closeToken {
  379. errExpected(closeToken, tokClose)
  380. }
  381. result.Strip = ast.NewStrip(tok.Val, tokClose.Val)
  382. return result
  383. }
  384. // partial : OPEN_PARTIAL partialName param* hash? CLOSE
  385. func (p *parser) parsePartial() *ast.PartialStatement {
  386. // OPEN_PARTIAL
  387. tok := p.shift()
  388. result := ast.NewPartialStatement(tok.Pos, tok.Line)
  389. // partialName
  390. result.Name = p.parsePartialName()
  391. // param* hash?
  392. result.Params, result.Hash = p.parseExpressionParamsHash()
  393. // CLOSE
  394. tokClose := p.shift()
  395. if tokClose.Kind != lexer.TokenClose {
  396. errExpected(lexer.TokenClose, tokClose)
  397. }
  398. result.Strip = ast.NewStrip(tok.Val, tokClose.Val)
  399. return result
  400. }
  401. // helperName | sexpr
  402. func (p *parser) parseHelperNameOrSexpr() ast.Node {
  403. if p.isSexpr() {
  404. // sexpr
  405. return p.parseSexpr()
  406. }
  407. // helperName
  408. return p.parseHelperName()
  409. }
  410. // param : helperName | sexpr
  411. func (p *parser) parseParam() ast.Node {
  412. return p.parseHelperNameOrSexpr()
  413. }
  414. // Returns true if next tokens represent a `param`
  415. func (p *parser) isParam() bool {
  416. return (p.isSexpr() || p.isHelperName()) && !p.isHashSegment()
  417. }
  418. // param*
  419. func (p *parser) parseParams() []ast.Node {
  420. var result []ast.Node
  421. for p.isParam() {
  422. result = append(result, p.parseParam())
  423. }
  424. return result
  425. }
  426. // sexpr : OPEN_SEXPR helperName param* hash? CLOSE_SEXPR
  427. func (p *parser) parseSexpr() *ast.SubExpression {
  428. // OPEN_SEXPR
  429. tok := p.shift()
  430. result := ast.NewSubExpression(tok.Pos, tok.Line)
  431. // helperName param* hash?
  432. result.Expression = p.parseExpression(tok)
  433. // CLOSE_SEXPR
  434. tok = p.shift()
  435. if tok.Kind != lexer.TokenCloseSexpr {
  436. errExpected(lexer.TokenCloseSexpr, tok)
  437. }
  438. return result
  439. }
  440. // hash : hashSegment+
  441. func (p *parser) parseHash() *ast.Hash {
  442. var pairs []*ast.HashPair
  443. for p.isHashSegment() {
  444. pairs = append(pairs, p.parseHashSegment())
  445. }
  446. firstLoc := pairs[0].Location()
  447. result := ast.NewHash(firstLoc.Pos, firstLoc.Line)
  448. result.Pairs = pairs
  449. return result
  450. }
  451. // returns true if next tokens represents a `hashSegment`
  452. func (p *parser) isHashSegment() bool {
  453. return p.have(2) && (p.next().Kind == lexer.TokenID) && (p.nextAt(1).Kind == lexer.TokenEquals)
  454. }
  455. // hashSegment : ID EQUALS param
  456. func (p *parser) parseHashSegment() *ast.HashPair {
  457. // ID
  458. tok := p.shift()
  459. // EQUALS
  460. p.shift()
  461. // param
  462. param := p.parseParam()
  463. result := ast.NewHashPair(tok.Pos, tok.Line)
  464. result.Key = tok.Val
  465. result.Val = param
  466. return result
  467. }
  468. // blockParams : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS
  469. func (p *parser) parseBlockParams() []string {
  470. var result []string
  471. // OPEN_BLOCK_PARAMS
  472. tok := p.shift()
  473. // ID+
  474. for p.isID() {
  475. result = append(result, p.shift().Val)
  476. }
  477. if len(result) == 0 {
  478. errExpected(lexer.TokenID, p.next())
  479. }
  480. // CLOSE_BLOCK_PARAMS
  481. tok = p.shift()
  482. if tok.Kind != lexer.TokenCloseBlockParams {
  483. errExpected(lexer.TokenCloseBlockParams, tok)
  484. }
  485. return result
  486. }
  487. // helperName : path | dataName | STRING | NUMBER | BOOLEAN | UNDEFINED | NULL
  488. func (p *parser) parseHelperName() ast.Node {
  489. var result ast.Node
  490. tok := p.next()
  491. switch tok.Kind {
  492. case lexer.TokenBoolean:
  493. // BOOLEAN
  494. p.shift()
  495. result = ast.NewBooleanLiteral(tok.Pos, tok.Line, (tok.Val == "true"), tok.Val)
  496. case lexer.TokenNumber:
  497. // NUMBER
  498. p.shift()
  499. val, isInt := parseNumber(tok)
  500. result = ast.NewNumberLiteral(tok.Pos, tok.Line, val, isInt, tok.Val)
  501. case lexer.TokenString:
  502. // STRING
  503. p.shift()
  504. result = ast.NewStringLiteral(tok.Pos, tok.Line, tok.Val)
  505. case lexer.TokenData:
  506. // dataName
  507. result = p.parseDataName()
  508. default:
  509. // path
  510. result = p.parsePath(false)
  511. }
  512. return result
  513. }
  514. // parseNumber parses a number
  515. func parseNumber(tok *lexer.Token) (result float64, isInt bool) {
  516. var valInt int
  517. var err error
  518. valInt, err = strconv.Atoi(tok.Val)
  519. if err == nil {
  520. isInt = true
  521. result = float64(valInt)
  522. } else {
  523. isInt = false
  524. result, err = strconv.ParseFloat(tok.Val, 64)
  525. if err != nil {
  526. errToken(tok, fmt.Sprintf("Failed to parse number: %s", tok.Val))
  527. }
  528. }
  529. // named returned values
  530. return
  531. }
  532. // Returns true if next tokens represent a `helperName`
  533. func (p *parser) isHelperName() bool {
  534. switch p.next().Kind {
  535. case lexer.TokenBoolean, lexer.TokenNumber, lexer.TokenString, lexer.TokenData, lexer.TokenID:
  536. return true
  537. }
  538. return false
  539. }
  540. // partialName : helperName | sexpr
  541. func (p *parser) parsePartialName() ast.Node {
  542. return p.parseHelperNameOrSexpr()
  543. }
  544. // dataName : DATA pathSegments
  545. func (p *parser) parseDataName() *ast.PathExpression {
  546. // DATA
  547. p.shift()
  548. // pathSegments
  549. return p.parsePath(true)
  550. }
  551. // path : pathSegments
  552. // pathSegments : pathSegments SEP ID
  553. // | ID
  554. func (p *parser) parsePath(data bool) *ast.PathExpression {
  555. var tok *lexer.Token
  556. // ID
  557. tok = p.shift()
  558. if tok.Kind != lexer.TokenID {
  559. errExpected(lexer.TokenID, tok)
  560. }
  561. result := ast.NewPathExpression(tok.Pos, tok.Line, data)
  562. result.Part(tok.Val)
  563. for p.isPathSep() {
  564. // SEP
  565. tok = p.shift()
  566. result.Sep(tok.Val)
  567. // ID
  568. tok = p.shift()
  569. if tok.Kind != lexer.TokenID {
  570. errExpected(lexer.TokenID, tok)
  571. }
  572. result.Part(tok.Val)
  573. if len(result.Parts) > 0 {
  574. switch tok.Val {
  575. case "..", ".", "this":
  576. errToken(tok, "Invalid path: "+result.Original)
  577. }
  578. }
  579. }
  580. return result
  581. }
  582. // Ensures there is token to parse at given index
  583. func (p *parser) ensure(index int) {
  584. if p.lexOver {
  585. // nothing more to grab
  586. return
  587. }
  588. nb := index + 1
  589. for len(p.tokens) < nb {
  590. // fetch next token
  591. tok := p.lex.NextToken()
  592. // queue it
  593. p.tokens = append(p.tokens, &tok)
  594. if (tok.Kind == lexer.TokenEOF) || (tok.Kind == lexer.TokenError) {
  595. p.lexOver = true
  596. break
  597. }
  598. }
  599. }
  600. // have returns true is there are a list given number of tokens to consume left
  601. func (p *parser) have(nb int) bool {
  602. p.ensure(nb - 1)
  603. return len(p.tokens) >= nb
  604. }
  605. // nextAt returns next token at given index, without consuming it
  606. func (p *parser) nextAt(index int) *lexer.Token {
  607. p.ensure(index)
  608. return p.tokens[index]
  609. }
  610. // next returns next token without consuming it
  611. func (p *parser) next() *lexer.Token {
  612. return p.nextAt(0)
  613. }
  614. // shift returns next token and remove it from the tokens buffer
  615. //
  616. // Panics if next token is `TokenError`
  617. func (p *parser) shift() *lexer.Token {
  618. var result *lexer.Token
  619. p.ensure(0)
  620. result, p.tokens = p.tokens[0], p.tokens[1:]
  621. // check error token
  622. if result.Kind == lexer.TokenError {
  623. errToken(result, "Lexer error")
  624. }
  625. return result
  626. }
  627. // isToken returns true if next token is of given type
  628. func (p *parser) isToken(kind lexer.TokenKind) bool {
  629. return p.have(1) && p.next().Kind == kind
  630. }
  631. // isSexpr returns true if next token starts a sexpr
  632. func (p *parser) isSexpr() bool {
  633. return p.isToken(lexer.TokenOpenSexpr)
  634. }
  635. // isPathSep returns true if next token is a path separator
  636. func (p *parser) isPathSep() bool {
  637. return p.isToken(lexer.TokenSep)
  638. }
  639. // isID returns true if next token is an ID
  640. func (p *parser) isID() bool {
  641. return p.isToken(lexer.TokenID)
  642. }
  643. // isBlockParams returns true if next token starts a block params
  644. func (p *parser) isBlockParams() bool {
  645. return p.isToken(lexer.TokenOpenBlockParams)
  646. }
  647. // isInverse returns true if next token starts an INVERSE sequence
  648. func (p *parser) isInverse() bool {
  649. return p.isToken(lexer.TokenInverse)
  650. }
  651. // isOpenInverseChain returns true if next token is OPEN_INVERSE_CHAIN
  652. func (p *parser) isOpenInverseChain() bool {
  653. return p.isToken(lexer.TokenOpenInverseChain)
  654. }