github.com/cloudflare/circl@v1.5.0/abe/cpabe/tkn20/internal/dsl/lexer.go (about) 1 package dsl 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 ) 8 9 var keywords = map[string]string{ 10 "and": And, 11 "or": Or, 12 "not": Not, 13 } 14 15 type Lexer struct { 16 source string 17 tokens []Token 18 start int 19 curr int 20 line int 21 hadError bool 22 } 23 24 func newLexer(source string) Lexer { 25 return Lexer{ 26 source: source, 27 tokens: nil, 28 start: 0, 29 curr: 0, 30 line: 1, 31 hadError: false, 32 } 33 } 34 35 func (l *Lexer) scanTokens() error { 36 errMsg := "unexpected character(s): " 37 for l.curr < len(l.source) { 38 l.start = l.curr 39 c := l.source[l.curr] 40 l.curr++ 41 switch c { 42 case '(': 43 l.addToken(LeftParen) 44 case ')': 45 l.addToken(RightParen) 46 case ':': 47 l.addToken(Colon) 48 case ' ', '\r', '\t': 49 case '\n': 50 l.line++ 51 default: 52 if isAlphaNumeric(c) { 53 l.identifier() 54 } else { 55 errMsg += fmt.Sprintf("'%s' ", string(c)) 56 l.hadError = true 57 } 58 } 59 } 60 l.addToken(EOF) 61 if l.hadError { 62 return errors.New(strings.TrimSpace(errMsg)) 63 } 64 return nil 65 } 66 67 func (l *Lexer) addToken(tokenType string) { 68 token := Token{ 69 tokenType, 70 l.source[l.start:l.curr], 71 l.line, 72 } 73 l.tokens = append(l.tokens, token) 74 } 75 76 func (l *Lexer) identifier() { 77 for l.curr < len(l.source) { 78 if isAlphaNumeric(l.source[l.curr]) { 79 l.curr++ 80 } else { 81 break 82 } 83 } 84 tokenType, ok := keywords[l.source[l.start:l.curr]] 85 if !ok { 86 tokenType = Identifier 87 } 88 l.addToken(tokenType) 89 }