parser.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package parser
  2. import (
  3. "fmt"
  4. "code.osinet.fr/fgm/waiig15/ast"
  5. "code.osinet.fr/fgm/waiig15/lexer"
  6. "code.osinet.fr/fgm/waiig15/token"
  7. )
  8. // Parser implements the parsing mechanism top-level layer.
  9. type Parser struct {
  10. errors []string
  11. l *lexer.Lexer
  12. curToken token.Token
  13. peekToken token.Token
  14. }
  15. // New returns a new Parser instance with the first two parser tokens already
  16. // loaded.
  17. func New(l *lexer.Lexer) *Parser {
  18. p := &Parser{
  19. l: l,
  20. errors: []string{},
  21. }
  22. // Read two tokens, so curToken and peeToken are both set.
  23. p.nextToken()
  24. p.nextToken()
  25. return p
  26. }
  27. // Errors is a getter for Parser.errors.
  28. func (p *Parser) Errors() []string {
  29. return p.errors
  30. }
  31. // ParseProgram is the outermost parsing logic, accumulating statements in a
  32. // Program instance and returning that instance once parsing is done.
  33. func (p *Parser) ParseProgram() *ast.Program {
  34. program := &ast.Program{
  35. Statements: []ast.Statement{},
  36. }
  37. for !p.curTokenIs(token.EOF) {
  38. stmt := p.parseStatement()
  39. if stmt != nil {
  40. program.Statements = append(program.Statements, stmt)
  41. }
  42. p.nextToken()
  43. }
  44. return program
  45. }
  46. // Is the current token in the parser of the given type ?
  47. func (p *Parser) curTokenIs(t token.TokenType) bool {
  48. return p.curToken.Type == t
  49. }
  50. // Is the next token in the parser of the given type ? If it is, consume it,
  51. // else don't.
  52. func (p *Parser) expectPeek(t token.TokenType) bool {
  53. if p.peekTokenIs(t) {
  54. p.nextToken()
  55. return true
  56. }
  57. p.peekError(t)
  58. return false
  59. }
  60. func (p *Parser) nextToken() {
  61. p.curToken = p.peekToken
  62. p.peekToken = p.l.NextToken()
  63. }
  64. func (p *Parser) parseStatement() ast.Statement {
  65. switch p.curToken.Type {
  66. case token.LET:
  67. return p.parseLetStatement()
  68. case token.RETURN:
  69. return p.parseReturnStatement()
  70. default:
  71. return nil
  72. }
  73. }
  74. // Log a mismatch error on the peek token type in the parser instance.
  75. //
  76. // - t is the type of token that was expected
  77. func (p *Parser) peekError(t token.TokenType) {
  78. msg := fmt.Sprintf("expected next token to be %s, got %s instead",
  79. t, p.peekToken.Type)
  80. p.errors = append(p.errors, msg)
  81. }
  82. // Is the next token in the parser of the given type ? Don't consume it.
  83. func (p *Parser) peekTokenIs(t token.TokenType) bool {
  84. return p.peekToken.Type == t
  85. }