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 }