github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/nomdl/lexer.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // This file incorporates work covered by the following copyright and 16 // permission notice: 17 // 18 // Copyright 2017 Attic Labs, Inc. All rights reserved. 19 // Licensed under the Apache License, version 2.0: 20 // http://www.apache.org/licenses/LICENSE-2.0 21 22 package nomdl 23 24 import ( 25 "fmt" 26 "text/scanner" 27 ) 28 29 type lexer struct { 30 scanner *scanner.Scanner 31 peekToken rune 32 } 33 34 func (lex *lexer) next() rune { 35 if lex.peekToken != 0 { 36 tok := lex.peekToken 37 lex.peekToken = 0 38 return tok 39 } 40 41 return lex.scanner.Scan() 42 } 43 44 func (lex *lexer) peek() rune { 45 if lex.peekToken != 0 { 46 return lex.peekToken 47 } 48 tok := lex.scanner.Scan() 49 lex.peekToken = tok 50 return tok 51 } 52 53 func (lex *lexer) pos() scanner.Position { 54 if lex.peekToken != 0 { 55 panic("Cannot use pos after peek") 56 } 57 return lex.scanner.Pos() 58 } 59 60 func (lex *lexer) tokenText() string { 61 if lex.peekToken != 0 { 62 panic("Cannot use tokenText after peek") 63 } 64 return lex.scanner.TokenText() 65 } 66 67 func (lex *lexer) eat(expected rune) rune { 68 tok := lex.next() 69 lex.check(expected, tok) 70 return tok 71 } 72 73 func (lex *lexer) eatIf(expected rune) bool { 74 tok := lex.peek() 75 if tok == expected { 76 lex.next() 77 return true 78 } 79 return false 80 } 81 82 func (lex *lexer) check(expected, actual rune) { 83 if actual != expected { 84 lex.tokenMismatch(expected, actual) 85 } 86 } 87 88 func (lex *lexer) tokenMismatch(expected, actual rune) { 89 raiseSyntaxError(fmt.Sprintf("Unexpected token %s, expected %s", scanner.TokenString(actual), scanner.TokenString(expected)), lex.pos()) 90 } 91 92 func (lex *lexer) unexpectedToken(actual rune) { 93 raiseSyntaxError(fmt.Sprintf("Unexpected token %s", scanner.TokenString(actual)), lex.pos()) 94 } 95 96 func raiseSyntaxError(msg string, pos scanner.Position) { 97 panic(syntaxError{ 98 msg: msg, 99 pos: pos, 100 }) 101 } 102 103 type syntaxError struct { 104 msg string 105 pos scanner.Position 106 } 107 108 func (e syntaxError) Error() string { 109 return fmt.Sprintf("%s, %s", e.msg, e.pos) 110 } 111 112 func catchSyntaxError(f func()) (errRes error) { 113 defer func() { 114 if err := recover(); err != nil { 115 if err, ok := err.(syntaxError); ok { 116 errRes = err 117 return 118 } 119 panic(err) 120 } 121 }() 122 123 f() 124 return 125 }