github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/go/nomdl/lexer.go (about)

     1  // Copyright 2017 Attic Labs, Inc. All rights reserved.
     2  // Licensed under the Apache License, version 2.0:
     3  // http://www.apache.org/licenses/LICENSE-2.0
     4  
     5  package nomdl
     6  
     7  import (
     8  	"fmt"
     9  	"text/scanner"
    10  )
    11  
    12  type lexer struct {
    13  	scanner   *scanner.Scanner
    14  	peekToken rune
    15  }
    16  
    17  func (lex *lexer) next() rune {
    18  	if lex.peekToken != 0 {
    19  		tok := lex.peekToken
    20  		lex.peekToken = 0
    21  		return tok
    22  	}
    23  
    24  	return lex.scanner.Scan()
    25  }
    26  
    27  func (lex *lexer) peek() rune {
    28  	if lex.peekToken != 0 {
    29  		return lex.peekToken
    30  	}
    31  	tok := lex.scanner.Scan()
    32  	lex.peekToken = tok
    33  	return tok
    34  }
    35  
    36  func (lex *lexer) pos() scanner.Position {
    37  	if lex.peekToken != 0 {
    38  		panic("Cannot use pos after peek")
    39  	}
    40  	return lex.scanner.Pos()
    41  }
    42  
    43  func (lex *lexer) tokenText() string {
    44  	if lex.peekToken != 0 {
    45  		panic("Cannot use tokenText after peek")
    46  	}
    47  	return lex.scanner.TokenText()
    48  }
    49  
    50  func (lex *lexer) eat(expected rune) rune {
    51  	tok := lex.next()
    52  	lex.check(expected, tok)
    53  	return tok
    54  }
    55  
    56  func (lex *lexer) eatIf(expected rune) bool {
    57  	tok := lex.peek()
    58  	if tok == expected {
    59  		lex.next()
    60  		return true
    61  	}
    62  	return false
    63  }
    64  
    65  func (lex *lexer) check(expected, actual rune) {
    66  	if actual != expected {
    67  		lex.tokenMismatch(expected, actual)
    68  	}
    69  }
    70  
    71  func (lex *lexer) tokenMismatch(expected, actual rune) {
    72  	raiseSyntaxError(fmt.Sprintf("Unexpected token %s, expected %s", scanner.TokenString(actual), scanner.TokenString(expected)), lex.pos())
    73  }
    74  
    75  func (lex *lexer) unexpectedToken(actual rune) {
    76  	raiseSyntaxError(fmt.Sprintf("Unexpected token %s", scanner.TokenString(actual)), lex.pos())
    77  }
    78  
    79  func raiseSyntaxError(msg string, pos scanner.Position) {
    80  	panic(syntaxError{
    81  		msg: msg,
    82  		pos: pos,
    83  	})
    84  }
    85  
    86  type syntaxError struct {
    87  	msg string
    88  	pos scanner.Position
    89  }
    90  
    91  func (e syntaxError) Error() string {
    92  	return fmt.Sprintf("%s, %s", e.msg, e.pos)
    93  }
    94  
    95  func catchSyntaxError(f func()) (errRes error) {
    96  	defer func() {
    97  		if err := recover(); err != nil {
    98  			if err, ok := err.(syntaxError); ok {
    99  				errRes = err
   100  				return
   101  			}
   102  			panic(err)
   103  		}
   104  	}()
   105  
   106  	f()
   107  	return
   108  }