lexer.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. package zygo
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "regexp"
  8. "strconv"
  9. "unicode/utf8"
  10. )
  11. type TokenType int
  12. const (
  13. TokenTypeEmpty TokenType = iota
  14. TokenLParen
  15. TokenRParen
  16. TokenLSquare
  17. TokenRSquare
  18. TokenLCurly
  19. TokenRCurly
  20. TokenDot
  21. TokenQuote
  22. TokenBacktick
  23. TokenTilde
  24. TokenTildeAt
  25. TokenSymbol
  26. TokenBool
  27. TokenDecimal
  28. TokenHex
  29. TokenOct
  30. TokenBinary
  31. TokenFloat
  32. TokenChar
  33. TokenString
  34. TokenCaret
  35. TokenColonOperator
  36. TokenThreadingOperator
  37. TokenBackslash
  38. TokenDollar
  39. TokenDotSymbol
  40. TokenFreshAssign
  41. TokenBacktickString
  42. TokenComment
  43. TokenBeginBlockComment
  44. TokenEndBlockComment
  45. TokenSemicolon
  46. TokenSymbolColon
  47. TokenComma
  48. TokenEnd
  49. )
  50. type Token struct {
  51. typ TokenType
  52. str string
  53. }
  54. var EndTk = Token{typ: TokenEnd}
  55. func (t Token) String() string {
  56. switch t.typ {
  57. case TokenLParen:
  58. return "("
  59. case TokenRParen:
  60. return ")"
  61. case TokenLSquare:
  62. return "["
  63. case TokenRSquare:
  64. return "]"
  65. case TokenLCurly:
  66. return "{"
  67. case TokenRCurly:
  68. return "}"
  69. case TokenDot:
  70. return t.str
  71. case TokenQuote:
  72. return "'"
  73. case TokenBacktick:
  74. return "`"
  75. case TokenCaret:
  76. return "^"
  77. case TokenTilde:
  78. return "~"
  79. case TokenTildeAt:
  80. return "~@"
  81. case TokenHex:
  82. return "0x" + t.str
  83. case TokenOct:
  84. return "0o" + t.str
  85. case TokenBinary:
  86. return "0b" + t.str
  87. case TokenChar:
  88. return strconv.Quote(t.str)
  89. case TokenColonOperator:
  90. return ":"
  91. case TokenThreadingOperator:
  92. return "->"
  93. case TokenBackslash:
  94. return "\\"
  95. case TokenDollar:
  96. return "$"
  97. }
  98. return t.str
  99. }
  100. type LexerState int
  101. const (
  102. LexerNormal LexerState = iota
  103. LexerCommentLine //
  104. LexerStrLit //
  105. LexerStrEscaped //
  106. LexerUnquote //
  107. LexerBacktickString //
  108. LexerFreshAssignOrColon
  109. LexerFirstFwdSlash // could be start of // comment or /*
  110. LexerCommentBlock
  111. LexerCommentBlockAsterisk // could be end of block comment */
  112. LexerBuiltinOperator
  113. )
  114. type Lexer struct {
  115. parser *Parser
  116. state LexerState
  117. prevrune rune
  118. tokens []Token
  119. buffer *bytes.Buffer
  120. prevToken Token
  121. prevPrevToken Token
  122. stream io.RuneScanner
  123. next []io.RuneScanner
  124. linenum int
  125. }
  126. func (lexer *Lexer) AppendToken(tok Token) {
  127. lexer.tokens = append(lexer.tokens, tok)
  128. lexer.prevPrevToken = lexer.prevToken
  129. lexer.prevToken = tok
  130. }
  131. func (lexer *Lexer) PrependToken(tok Token) {
  132. lexer.tokens = append([]Token{tok}, lexer.tokens...)
  133. }
  134. func NewLexer(p *Parser) *Lexer {
  135. return &Lexer{
  136. parser: p,
  137. tokens: make([]Token, 0, 10),
  138. buffer: new(bytes.Buffer),
  139. state: LexerNormal,
  140. linenum: 1,
  141. }
  142. }
  143. func (lexer *Lexer) Linenum() int {
  144. return lexer.linenum
  145. }
  146. func (lex *Lexer) Reset() {
  147. lex.stream = nil
  148. lex.tokens = lex.tokens[:0]
  149. lex.state = LexerNormal
  150. lex.linenum = 1
  151. lex.buffer.Reset()
  152. }
  153. func (lex *Lexer) EmptyToken() Token {
  154. return Token{}
  155. }
  156. func (lex *Lexer) Token(typ TokenType, str string) Token {
  157. t := Token{
  158. typ: typ,
  159. str: str,
  160. }
  161. return t
  162. }
  163. var (
  164. BoolRegex = regexp.MustCompile("^(true|false)$")
  165. DecimalRegex = regexp.MustCompile("^-?[0-9]+$")
  166. HexRegex = regexp.MustCompile("^0x[0-9a-fA-F]+$")
  167. OctRegex = regexp.MustCompile("^0o[0-7]+$")
  168. BinaryRegex = regexp.MustCompile("^0b[01]+$")
  169. // SymbolRegex = regexp.MustCompile("^[^'#]+$")
  170. // (Sigil) symbols can begin with #, $, ?, but
  171. // sigils cannot appear later in any symbol.
  172. // Symbols cannot contain whitespace nor `~`, `@`, `(`, `)`, `[`, `]`,
  173. // `{`, `}`, `'`, `#`, `^`, `\`, `|`, `%`, `"`, `;`. They can optionally
  174. // end in `:`.
  175. // Nor, obviously, can symbols contain backticks, "`".
  176. // Symbols cannot start with a number. DotSymbols cannot have a number
  177. // as the first character after '.'
  178. SymbolRegex = regexp.MustCompile(`^[#$?]?[^#$?':;\\~@\[\]{}\^|"()%0-9,&][^'#:;\\~@\[\]{}\^|"()%,&*\-]*[:]?$`)
  179. // dot symbol examples: `.`, `.a`, `.a.b`, `.a.b.c`
  180. // dot symbol non-examples: `.a.`, `..`
  181. DotSymbolRegex = regexp.MustCompile(`^[.]$|^([.][^'#:;\\~@\[\]{}\^|"()%.0-9,][^'#:;\\~@\[\]{}\^|"()%.,*+\-]*)+$|^[^'#:;\\~@\[\]{}\^|"()%.0-9,][^'#:;\\~@\[\]{}\^|"()%.,*+\-]*([.][^'#:;\\~@\[\]{}\^|"()%.0-9,][^'#:;\\~@\[\]{}\^|"()%.,*+\-]*)+$`)
  182. DotPartsRegex = regexp.MustCompile(`[.]?[^'#:;\\~@\[\]{}\^|"()%.0-9,][^'#:;\\~@\[\]{}\^|"()%.,]*`)
  183. CharRegex = regexp.MustCompile("^'\\\\?.'$")
  184. FloatRegex = regexp.MustCompile("^-?([0-9]+\\.[0-9]*)$|-?(\\.[0-9]+)$|-?([0-9]+(\\.[0-9]*)?[eE](-?[0-9]+))$")
  185. ComplexRegex = regexp.MustCompile("^-?([0-9]+\\.[0-9]*)i?$|-?(\\.[0-9]+)i?$|-?([0-9]+(\\.[0-9]*)?[eE](-?[0-9]+))i?$")
  186. BuiltinOpRegex = regexp.MustCompile(`^(\+\+|\-\-|\+=|\-=|=|==|:=|\+|\-|\*|<|>|<=|>=|<-|->|\*=|/=|\*\*|!|!=|<!)$`)
  187. )
  188. func StringToRunes(str string) []rune {
  189. b := []byte(str)
  190. runes := make([]rune, 0)
  191. for len(b) > 0 {
  192. r, size := utf8.DecodeRune(b)
  193. runes = append(runes, r)
  194. b = b[size:]
  195. }
  196. return runes
  197. }
  198. func EscapeChar(char rune) (rune, error) {
  199. switch char {
  200. case 'n':
  201. return '\n', nil
  202. case 'r':
  203. return '\r', nil
  204. case 'a':
  205. return '\a', nil
  206. case 't':
  207. return '\t', nil
  208. case '\\':
  209. return '\\', nil
  210. case '"':
  211. return '"', nil
  212. case '\'':
  213. return '\'', nil
  214. case '#':
  215. return '#', nil
  216. }
  217. return ' ', errors.New("invalid escape sequence")
  218. }
  219. func DecodeChar(atom string) (string, error) {
  220. runes := StringToRunes(atom)
  221. n := len(runes)
  222. runes = runes[:n-1]
  223. runes = runes[1:]
  224. if len(runes) == 2 {
  225. char, err := EscapeChar(runes[1])
  226. return string(char), err
  227. }
  228. if len(runes) == 1 {
  229. return string(runes[0]), nil
  230. }
  231. return "", errors.New("not a char literal")
  232. }
  233. func (x *Lexer) DecodeAtom(atom string) (Token, error) {
  234. if atom == "&" {
  235. return x.Token(TokenSymbol, "&"), nil
  236. }
  237. if atom == "\\" {
  238. return x.Token(TokenBackslash, ""), nil
  239. }
  240. if BoolRegex.MatchString(atom) {
  241. return x.Token(TokenBool, atom), nil
  242. }
  243. if DecimalRegex.MatchString(atom) {
  244. return x.Token(TokenDecimal, atom), nil
  245. }
  246. if HexRegex.MatchString(atom) {
  247. return x.Token(TokenHex, atom[2:]), nil
  248. }
  249. if OctRegex.MatchString(atom) {
  250. return x.Token(TokenOct, atom[2:]), nil
  251. }
  252. if BinaryRegex.MatchString(atom) {
  253. return x.Token(TokenBinary, atom[2:]), nil
  254. }
  255. if FloatRegex.MatchString(atom) {
  256. return x.Token(TokenFloat, atom), nil
  257. }
  258. if DotSymbolRegex.MatchString(atom) {
  259. //Q("matched DotSymbolRegex '%v'", atom)
  260. return x.Token(TokenDotSymbol, atom), nil
  261. }
  262. if BuiltinOpRegex.MatchString(atom) {
  263. return x.Token(TokenSymbol, atom), nil
  264. }
  265. if atom == ":" {
  266. return x.Token(TokenSymbol, atom), nil
  267. } else if SymbolRegex.MatchString(atom) {
  268. ////Q("matched symbol regex, atom='%v'", atom)
  269. n := len(atom)
  270. if atom[n-1] == ':' {
  271. ////Q("matched symbol regex with colon, atom[:n-1]='%v'", atom[:n-1])
  272. return x.Token(TokenSymbolColon, atom[:n-1]), nil
  273. }
  274. return x.Token(TokenSymbol, atom), nil
  275. }
  276. if CharRegex.MatchString(atom) {
  277. char, err := DecodeChar(atom)
  278. if err != nil {
  279. return x.EmptyToken(), err
  280. }
  281. return x.Token(TokenChar, char), nil
  282. }
  283. return x.EmptyToken(), fmt.Errorf("Unrecognized atom: '%s'", atom)
  284. }
  285. func (lexer *Lexer) dumpBuffer() error {
  286. n := lexer.buffer.Len()
  287. if n <= 0 {
  288. return nil
  289. }
  290. tok, err := lexer.DecodeAtom(lexer.buffer.String())
  291. if err != nil {
  292. return err
  293. }
  294. lexer.buffer.Reset()
  295. lexer.AppendToken(tok)
  296. return nil
  297. }
  298. // with block comments, we've got to tell
  299. // the parser about them, so it can recognize
  300. // when another line is needed to finish a
  301. // block comment.
  302. func (lexer *Lexer) dumpComment() {
  303. str := lexer.buffer.String()
  304. lexer.buffer.Reset()
  305. lexer.AppendToken(lexer.Token(TokenComment, str))
  306. }
  307. func (lexer *Lexer) dumpString() {
  308. str := lexer.buffer.String()
  309. lexer.buffer.Reset()
  310. lexer.AppendToken(lexer.Token(TokenString, str))
  311. }
  312. func (lexer *Lexer) dumpBacktickString() {
  313. str := lexer.buffer.String()
  314. lexer.buffer.Reset()
  315. lexer.AppendToken(lexer.Token(TokenBacktickString, str))
  316. }
  317. func (x *Lexer) DecodeBrace(brace rune) Token {
  318. switch brace {
  319. case '(':
  320. return x.Token(TokenLParen, "")
  321. case ')':
  322. return x.Token(TokenRParen, "")
  323. case '[':
  324. return x.Token(TokenLSquare, "")
  325. case ']':
  326. return x.Token(TokenRSquare, "")
  327. case '{':
  328. return x.Token(TokenLCurly, "")
  329. case '}':
  330. return x.Token(TokenRCurly, "")
  331. }
  332. return EndTk
  333. }
  334. func (lexer *Lexer) LexNextRune(r rune) error {
  335. top:
  336. switch lexer.state {
  337. case LexerCommentBlock:
  338. //Q("lexer.state = LexerCommentBlock")
  339. if r == '\n' {
  340. _, err := lexer.buffer.WriteRune('\n')
  341. if err != nil {
  342. return err
  343. }
  344. lexer.dumpComment()
  345. // stay in LexerCommentBlock
  346. return nil
  347. }
  348. if r == '*' {
  349. lexer.state = LexerCommentBlockAsterisk
  350. return nil
  351. }
  352. case LexerCommentBlockAsterisk:
  353. //Q("lexer.state = LexerCommentBlockAsterisk")
  354. if r == '/' {
  355. _, err := lexer.buffer.WriteString("*/")
  356. if err != nil {
  357. return err
  358. }
  359. lexer.dumpComment()
  360. lexer.AppendToken(lexer.Token(TokenEndBlockComment, ""))
  361. lexer.state = LexerNormal
  362. return nil
  363. }
  364. _, err := lexer.buffer.WriteRune('*')
  365. if err != nil {
  366. return err
  367. }
  368. lexer.state = LexerCommentBlock
  369. goto writeRuneToBuffer
  370. case LexerFirstFwdSlash:
  371. //Q("lexer.state = LexerFirstFwdSlash")
  372. if r == '/' {
  373. err := lexer.dumpBuffer()
  374. if err != nil {
  375. return err
  376. }
  377. lexer.state = LexerCommentLine
  378. _, err = lexer.buffer.WriteString("//")
  379. return err
  380. }
  381. if r == '*' {
  382. err := lexer.dumpBuffer()
  383. if err != nil {
  384. return err
  385. }
  386. _, err = lexer.buffer.WriteString("/*")
  387. if err != nil {
  388. return err
  389. }
  390. lexer.state = LexerCommentBlock
  391. lexer.AppendToken(lexer.Token(TokenBeginBlockComment, ""))
  392. return nil
  393. }
  394. lexer.state = LexerBuiltinOperator
  395. lexer.prevrune = '/'
  396. err := lexer.dumpBuffer() // don't mix with token before the /
  397. if err != nil {
  398. return err
  399. }
  400. goto top // process the unknown rune r
  401. case LexerCommentLine:
  402. //Q("lexer.state = LexerCommentLine")
  403. if r == '\n' {
  404. //Q("lexer.state = LexerCommentLine sees end of line comment: '%s', going to LexerNormal", string(lexer.buffer.Bytes()))
  405. lexer.dumpComment()
  406. lexer.state = LexerNormal
  407. return nil
  408. }
  409. case LexerBacktickString:
  410. if r == '`' {
  411. lexer.dumpBacktickString()
  412. lexer.state = LexerNormal
  413. return nil
  414. }
  415. lexer.buffer.WriteRune(r)
  416. return nil
  417. case LexerStrLit:
  418. if r == '\\' {
  419. lexer.state = LexerStrEscaped
  420. return nil
  421. }
  422. if r == '"' {
  423. lexer.dumpString()
  424. lexer.state = LexerNormal
  425. return nil
  426. }
  427. lexer.buffer.WriteRune(r)
  428. return nil
  429. case LexerStrEscaped:
  430. char, err := EscapeChar(r)
  431. if err != nil {
  432. return err
  433. }
  434. lexer.buffer.WriteRune(char)
  435. lexer.state = LexerStrLit
  436. return nil
  437. case LexerUnquote:
  438. if r == '@' {
  439. lexer.AppendToken(lexer.Token(TokenTildeAt, ""))
  440. } else {
  441. lexer.AppendToken(lexer.Token(TokenTilde, ""))
  442. lexer.buffer.WriteRune(r)
  443. }
  444. lexer.state = LexerNormal
  445. return nil
  446. case LexerFreshAssignOrColon:
  447. lexer.state = LexerNormal
  448. // there was a ':' followed by either '=' or something other than '=',
  449. // so proceed to process the normal ':' actions.
  450. if lexer.buffer.Len() == 0 {
  451. if r == '=' {
  452. lexer.AppendToken(lexer.Token(TokenFreshAssign, ":="))
  453. return nil
  454. }
  455. }
  456. if r == '=' {
  457. err := lexer.dumpBuffer()
  458. if err != nil {
  459. return err
  460. }
  461. lexer.AppendToken(lexer.Token(TokenFreshAssign, ":="))
  462. return nil
  463. } else {
  464. // but still allow ':' to be a token terminator at the end of a word.
  465. _, err := lexer.buffer.WriteRune(':')
  466. if err != nil {
  467. return err
  468. }
  469. err = lexer.dumpBuffer()
  470. if err != nil {
  471. return err
  472. }
  473. goto top // process the unknown rune r in Normal mode
  474. }
  475. case LexerBuiltinOperator:
  476. //Q("in LexerBuiltinOperator")
  477. lexer.state = LexerNormal
  478. // three cases: negative number, one rune operator, two rune operator
  479. first := string(lexer.prevrune)
  480. atom := fmt.Sprintf("%c%c", lexer.prevrune, r)
  481. //Q("in LexerBuiltinOperator, first='%s', atom='%s'", first, atom)
  482. // are we a negative number -1 or -.1 rather than ->, --, -= operator?
  483. if lexer.prevrune == '-' {
  484. if FloatRegex.MatchString(atom) || DecimalRegex.MatchString(atom) {
  485. //Q("'%s' is the beginning of a negative number", atom)
  486. _, err := lexer.buffer.WriteString(atom)
  487. if err != nil {
  488. return err
  489. }
  490. return nil
  491. } else {
  492. //Q("atom was not matched by FloatRegex: '%s'", atom)
  493. }
  494. }
  495. if BuiltinOpRegex.MatchString(atom) {
  496. //Q("2 rune atom in builtin op '%s', first='%s'", atom, first)
  497. // 2 rune op
  498. lexer.AppendToken(lexer.Token(TokenSymbol, atom))
  499. return nil
  500. }
  501. //Q("1 rune atom in builtin op '%s', first='%s'", atom, first)
  502. lexer.AppendToken(lexer.Token(TokenSymbol, first))
  503. goto top // still have to parse r in normal
  504. case LexerNormal:
  505. switch r {
  506. case '*':
  507. fallthrough
  508. case '+':
  509. fallthrough
  510. case '-':
  511. fallthrough
  512. case '<':
  513. fallthrough
  514. case '>':
  515. fallthrough
  516. case '=':
  517. fallthrough
  518. case '!':
  519. err := lexer.dumpBuffer()
  520. if err != nil {
  521. return err
  522. }
  523. lexer.state = LexerBuiltinOperator
  524. lexer.prevrune = r
  525. return nil
  526. case '/':
  527. lexer.state = LexerFirstFwdSlash
  528. return nil
  529. case '`':
  530. if lexer.buffer.Len() > 0 {
  531. return errors.New("Unexpected backtick")
  532. }
  533. lexer.state = LexerBacktickString
  534. return nil
  535. case '"':
  536. if lexer.buffer.Len() > 0 {
  537. return errors.New("Unexpected quote")
  538. }
  539. lexer.state = LexerStrLit
  540. return nil
  541. case ';':
  542. err := lexer.dumpBuffer()
  543. if err != nil {
  544. return err
  545. }
  546. lexer.AppendToken(lexer.Token(TokenSemicolon, ";"))
  547. return nil
  548. case ',':
  549. err := lexer.dumpBuffer()
  550. if err != nil {
  551. return err
  552. }
  553. lexer.AppendToken(lexer.Token(TokenComma, ","))
  554. return nil
  555. // colon terminates a keyword symbol, e.g. in `mykey: "myvalue"`;
  556. // mykey is the symbol.
  557. // Exception: unless it is the := operator for fresh assigment.
  558. case ':':
  559. lexer.state = LexerFreshAssignOrColon
  560. // won't know if it is ':' alone or ':=' for sure
  561. // until we get the next rune
  562. return nil
  563. // likewise &
  564. case '&':
  565. err := lexer.dumpBuffer()
  566. if err != nil {
  567. return err
  568. }
  569. lexer.AppendToken(lexer.Token(TokenSymbol, "&"))
  570. return nil
  571. case '%': // replaces ' as our quote shorthand
  572. if lexer.buffer.Len() > 0 {
  573. return errors.New("Unexpected % quote")
  574. }
  575. lexer.AppendToken(lexer.Token(TokenQuote, ""))
  576. return nil
  577. // caret '^' replaces backtick '`' as the start of a macro template, so
  578. // we can use `` as in Go for verbatim strings (strings with newlines, etc).
  579. case '^':
  580. if lexer.buffer.Len() > 0 {
  581. return errors.New("Unexpected ^ caret")
  582. }
  583. lexer.AppendToken(lexer.Token(TokenCaret, ""))
  584. return nil
  585. case '~':
  586. if lexer.buffer.Len() > 0 {
  587. return errors.New("Unexpected tilde")
  588. }
  589. lexer.state = LexerUnquote
  590. return nil
  591. case '(':
  592. fallthrough
  593. case ')':
  594. fallthrough
  595. case '[':
  596. fallthrough
  597. case ']':
  598. fallthrough
  599. case '{':
  600. fallthrough
  601. case '}':
  602. err := lexer.dumpBuffer()
  603. if err != nil {
  604. return err
  605. }
  606. lexer.AppendToken(lexer.DecodeBrace(r))
  607. return nil
  608. case '\n':
  609. lexer.linenum++
  610. fallthrough
  611. case ' ':
  612. fallthrough
  613. case '\t':
  614. fallthrough
  615. case '\r':
  616. err := lexer.dumpBuffer()
  617. if err != nil {
  618. return err
  619. }
  620. return nil
  621. } // end switch r in LexerNormal state
  622. } // end switch lexer.state
  623. writeRuneToBuffer:
  624. _, err := lexer.buffer.WriteRune(r)
  625. if err != nil {
  626. return err
  627. }
  628. return nil
  629. }
  630. // peekNextToken returns EndTk when it has nothing left.
  631. func (lexer *Lexer) peekNextToken() (tok Token, err error) {
  632. if lexer.stream == nil {
  633. if !lexer.PromoteNextStream() {
  634. return EndTk, nil
  635. }
  636. }
  637. for len(lexer.tokens) == 0 {
  638. r, _, err := lexer.stream.ReadRune()
  639. if err != nil {
  640. if lexer.PromoteNextStream() {
  641. continue
  642. } else {
  643. return EndTk, nil
  644. }
  645. }
  646. err = lexer.LexNextRune(r)
  647. if err != nil {
  648. return EndTk, err
  649. }
  650. }
  651. tok = lexer.tokens[0]
  652. return tok, nil
  653. }
  654. func (lexer *Lexer) GetNextToken() (tok Token, err error) {
  655. /*
  656. Q("\n in GetNextToken()\n")
  657. defer func() {
  658. Q("\n done with GetNextToken() -> returning tok='%v', err=%v. lexer.buffer.String()='%s'\n",
  659. tok, err, lexer.buffer.String())
  660. }()
  661. */
  662. tok, err = lexer.peekNextToken()
  663. if err != nil || tok.typ == TokenEnd {
  664. return EndTk, err
  665. }
  666. lexer.tokens = lexer.tokens[1:]
  667. return tok, nil
  668. }
  669. func (lex *Lexer) PromoteNextStream() (ok bool) {
  670. /*
  671. Q("entering PromoteNextStream()!\n")
  672. defer func() {
  673. Q("done with PromoteNextStream, promoted=%v\n", ok)
  674. }()
  675. */
  676. if len(lex.next) == 0 {
  677. return false
  678. }
  679. //Q("Promoting next stream!\n")
  680. lex.stream = lex.next[0]
  681. lex.next = lex.next[1:]
  682. return true
  683. }
  684. func (lex *Lexer) AddNextStream(s io.RuneScanner) {
  685. // in case we still have input available,
  686. // save new stuff for later
  687. lex.next = append(lex.next, s)
  688. if lex.stream == nil {
  689. lex.PromoteNextStream()
  690. } else {
  691. _, _, err := lex.stream.ReadRune()
  692. if err == nil {
  693. lex.stream.UnreadRune()
  694. // still have input available
  695. return
  696. } else {
  697. lex.PromoteNextStream()
  698. }
  699. }
  700. }