parser.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package parser
  2. import (
  3. "code.osinet.fr/fgm/waiig15/ast"
  4. "code.osinet.fr/fgm/waiig15/lexer"
  5. "code.osinet.fr/fgm/waiig15/token"
  6. "fmt"
  7. )
  8. type Parser struct {
  9. errors []string
  10. l *lexer.Lexer
  11. curToken token.Token
  12. peekToken token.Token
  13. }
  14. func New(l *lexer.Lexer) *Parser {
  15. p := &Parser{
  16. l: l,
  17. errors: []string{},
  18. }
  19. // Read two tokens, so curToken and peeToken are both set.
  20. p.nextToken()
  21. p.nextToken()
  22. return p
  23. }
  24. func (p *Parser) Errors() []string {
  25. return p.errors
  26. }
  27. func (p *Parser) ParseProgram() *ast.Program {
  28. program := &ast.Program{
  29. Statements: []ast.Statement{},
  30. }
  31. for !p.curTokenIs(token.EOF) {
  32. stmt := p.parseStatement()
  33. if stmt != nil {
  34. program.Statements = append(program.Statements, stmt)
  35. }
  36. p.nextToken()
  37. }
  38. return program
  39. }
  40. // Is the current token in the parser of the given type ?
  41. func (p *Parser) curTokenIs(t token.TokenType) bool {
  42. return p.curToken.Type == t
  43. }
  44. // Is the next token in the parser of the given type ? If it is, consume it,
  45. // else don't.
  46. func (p *Parser) expectPeek(t token.TokenType) bool {
  47. if p.peekTokenIs(t) {
  48. p.nextToken()
  49. return true
  50. } else {
  51. p.peekError(t)
  52. return false
  53. }
  54. }
  55. func (p *Parser) nextToken() {
  56. p.curToken = p.peekToken
  57. p.peekToken = p.l.NextToken()
  58. }
  59. func (p *Parser) parseLetStatement() *ast.LetStatement {
  60. stmt := &ast.LetStatement{
  61. Token: p.curToken,
  62. }
  63. // Let statement starts with an IDENT token, so if next token is not an
  64. // IDENT, the next statement cannot be a Let statement.
  65. if !p.expectPeek(token.IDENT) {
  66. return nil
  67. }
  68. stmt.Name = &ast.Identifier{
  69. Token: p.curToken,
  70. Value: p.curToken.Literal,
  71. }
  72. // The previous expectPeek() call fetched the next token, so we should now
  73. // be on the assignment.
  74. if !p.expectPeek(token.ASSIGN) {
  75. return nil
  76. }
  77. // Skip the expression for now, progress to the semicolon terminating the
  78. // statement.
  79. for !p.curTokenIs(token.SEMICOLON) {
  80. p.nextToken()
  81. }
  82. return stmt
  83. }
  84. func (p *Parser) parseStatement() ast.Statement {
  85. switch p.curToken.Type {
  86. case token.LET:
  87. return p.parseLetStatement()
  88. default:
  89. return nil
  90. }
  91. }
  92. // Log a mismatch error on the peek token type in the parser instance.
  93. //
  94. // - t is the type of token that was expected
  95. func (p *Parser) peekError(t token.TokenType) {
  96. msg := fmt.Sprintf("expected next token to be %s, got %s instead",
  97. t, p.peekToken.Type)
  98. p.errors = append(p.errors, msg)
  99. }
  100. // Is the next token in the parser of the given type ? Don't consume it.
  101. func (p *Parser) peekTokenIs(t token.TokenType) bool {
  102. return p.peekToken.Type == t
  103. }