gonum.org/v1/gonum@v0.14.0/graph/formats/dot/internal/errors/errors.go (about) 1 // Code generated by gocc; DO NOT EDIT. 2 3 // This file is dual licensed under CC0 and The Gonum License. 4 // 5 // Copyright ©2017 The Gonum Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 // 9 // Copyright ©2017 Robin Eklind. 10 // This file is made available under a Creative Commons CC0 1.0 11 // Universal Public Domain Dedication. 12 13 package errors 14 15 import ( 16 "fmt" 17 "strconv" 18 "strings" 19 "unicode" 20 21 "gonum.org/v1/gonum/graph/formats/dot/internal/token" 22 ) 23 24 type ErrorSymbol interface { 25 } 26 27 type Error struct { 28 Err error 29 ErrorToken *token.Token 30 ErrorSymbols []ErrorSymbol 31 ExpectedTokens []string 32 StackTop int 33 } 34 35 func (e *Error) String() string { 36 w := new(strings.Builder) 37 if e.Err != nil { 38 fmt.Fprintln(w, "Error ", e.Err) 39 } else { 40 fmt.Fprintln(w, "Error") 41 } 42 fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) 43 fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) 44 fmt.Fprint(w, "Expected one of: ") 45 for _, sym := range e.ExpectedTokens { 46 fmt.Fprint(w, string(sym), " ") 47 } 48 fmt.Fprintln(w, "ErrorSymbol:") 49 for _, sym := range e.ErrorSymbols { 50 fmt.Fprintf(w, "%v\n", sym) 51 } 52 53 return w.String() 54 } 55 56 func DescribeExpected(tokens []string) string { 57 switch len(tokens) { 58 case 0: 59 return "unexpected additional tokens" 60 61 case 1: 62 return "expected " + tokens[0] 63 64 case 2: 65 return "expected either " + tokens[0] + " or " + tokens[1] 66 67 case 3: 68 // Oxford-comma rules require more than 3 items in a list for the 69 // comma to appear before the 'or' 70 return fmt.Sprintf("expected one of %s, %s or %s", tokens[0], tokens[1], tokens[2]) 71 72 default: 73 // Oxford-comma separated alternatives list. 74 tokens = append(tokens[:len(tokens)-1], "or "+tokens[len(tokens)-1]) 75 return "expected one of " + strings.Join(tokens, ", ") 76 } 77 } 78 79 func DescribeToken(tok *token.Token) string { 80 switch tok.Type { 81 case token.INVALID: 82 return fmt.Sprintf("unknown/invalid token %q", tok.Lit) 83 case token.EOF: 84 return "end-of-file" 85 default: 86 return fmt.Sprintf("%q", tok.Lit) 87 } 88 } 89 90 func (e *Error) Error() string { 91 // identify the line and column of the error in 'gnu' style so it can be understood 92 // by editors and IDEs; user will need to prefix it with a filename. 93 text := fmt.Sprintf("%d:%d: error: ", e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) 94 95 // See if the error token can provide us with the filename. 96 switch src := e.ErrorToken.Pos.Context.(type) { 97 case token.Sourcer: 98 text = src.Source() + ":" + text 99 } 100 101 if e.Err != nil { 102 // Custom error specified, e.g. by << nil, errors.New("missing newline") >> 103 text += e.Err.Error() 104 } else { 105 tokens := make([]string, len(e.ExpectedTokens)) 106 for idx, token := range e.ExpectedTokens { 107 if !unicode.IsLetter(rune(token[0])) { 108 token = strconv.Quote(token) 109 } 110 tokens[idx] = token 111 } 112 text += DescribeExpected(tokens) 113 actual := DescribeToken(e.ErrorToken) 114 text += fmt.Sprintf("; got: %s", actual) 115 } 116 117 return text 118 }