range.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright (c) 2017 Ernest Micklei
  2. //
  3. // MIT License
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining
  6. // a copy of this software and associated documentation files (the
  7. // "Software"), to deal in the Software without restriction, including
  8. // without limitation the rights to use, copy, modify, merge, publish,
  9. // distribute, sublicense, and/or sell copies of the Software, and to
  10. // permit persons to whom the Software is furnished to do so, subject to
  11. // the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. package proto
  24. import (
  25. "fmt"
  26. "strconv"
  27. )
  28. // Range is to specify number intervals (with special end value "max")
  29. type Range struct {
  30. From, To int
  31. Max bool
  32. }
  33. // SourceRepresentation return a single number if from = to. Returns <from> to <to> otherwise unless Max then return <from> to max.
  34. func (r Range) SourceRepresentation() string {
  35. if r.Max {
  36. return fmt.Sprintf("%d to max", r.From)
  37. }
  38. if r.From == r.To {
  39. return strconv.Itoa(r.From)
  40. }
  41. return fmt.Sprintf("%d to %d", r.From, r.To)
  42. }
  43. // parseRanges is used to parse ranges for extensions and reserved
  44. func parseRanges(p *Parser, n Visitee) (list []Range, err error) {
  45. seenTo := false
  46. for {
  47. pos, tok, lit := p.next()
  48. if isString(lit) {
  49. return list, p.unexpected(lit, "integer, <to> <max>", n)
  50. }
  51. switch lit {
  52. case ",":
  53. case "to":
  54. seenTo = true
  55. case ";":
  56. p.nextPut(pos, tok, lit) // allow for inline comment parsing
  57. goto done
  58. case "max":
  59. if !seenTo {
  60. return list, p.unexpected(lit, "to", n)
  61. }
  62. from := list[len(list)-1]
  63. list = append(list[0:len(list)-1], Range{From: from.From, Max: true})
  64. default:
  65. // must be number
  66. i, err := strconv.Atoi(lit)
  67. if err != nil {
  68. return list, p.unexpected(lit, "range integer", n)
  69. }
  70. if seenTo {
  71. // replace last two ranges with one
  72. if len(list) < 1 {
  73. p.unexpected(lit, "integer", n)
  74. }
  75. from := list[len(list)-1]
  76. list = append(list[0:len(list)-1], Range{From: from.From, To: i})
  77. seenTo = false
  78. } else {
  79. list = append(list, Range{From: i, To: i})
  80. }
  81. }
  82. }
  83. done:
  84. return
  85. }