scanner.mx raw

   1  package syntax
   2  
   3  import (
   4  	"io"
   5  	"git.smesh.lol/moxie/pkg/token"
   6  	"unicode/utf8"
   7  )
   8  
   9  const (
  10  	comments   uint32 = 1 << iota
  11  	directives
  12  )
  13  
  14  const maxRune = 0x10FFFF
  15  
  16  func isLetter(ch rune) (ok bool) {
  17  	if ch < 0x80 {
  18  		return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'
  19  	}
  20  	return ch >= 0xC0
  21  }
  22  
  23  func isDigit(ch rune) (ok bool) {
  24  	if ch < 0x80 {
  25  		return ch >= '0' && ch <= '9'
  26  	}
  27  	return false
  28  }
  29  
  30  
  31  type Scanner struct {
  32  	Source
  33  	mode   uint32
  34  	nlsemi bool
  35  
  36  	Line, Col uint32
  37  	Blank     bool
  38  	Tok       token.Token
  39  	Lit       string
  40  	Bad       bool
  41  	Kind      token.LitKind
  42  	Op        token.Operator
  43  	Prec      int32
  44  
  45  	keywordMap   [1 << 6]token.Token
  46  	keywordsReady bool
  47  }
  48  
  49  func (s *Scanner) Init(src io.Reader, errh func(line, col uint32, msg string), mode uint32) {
  50  	s.Source.init(src, errh)
  51  	s.mode = mode
  52  	s.nlsemi = false
  53  	s.initKeywords()
  54  }
  55  
  56  func (s *Scanner) InitBytes(src []byte, errh func(line, col uint32, msg string), mode uint32) {
  57  	s.Source.initBytes(src, errh)
  58  	s.mode = 0
  59  	s.nlsemi = false
  60  	s.initKeywords()
  61  }
  62  
  63  func (s *Scanner) Errorf(msg string) {
  64  	s.error(msg)
  65  }
  66  
  67  func (s *Scanner) ErrorAtf(offset int32, msg string) {
  68  	s.errh(s.line, s.col+uint32(offset), msg)
  69  }
  70  
  71  func (s *Scanner) SetLit(kind token.LitKind, ok bool) {
  72  	s.nlsemi = true
  73  	s.Tok = token.Literal
  74  	s.Lit = string(s.segmentCopy())
  75  	s.Bad = !ok
  76  	s.Kind = kind
  77  }
  78  
  79  func (s *Scanner) Next() {
  80  	nlsemi := s.nlsemi
  81  	s.nlsemi = false
  82  
  83  redo:
  84  	s.stop()
  85  	startLine, startCol := s.pos()
  86  	for s.ch == ' ' || s.ch == '\t' || s.ch == '\n' && !nlsemi || s.ch == '\r' {
  87  		s.nextch()
  88  	}
  89  
  90  	s.Line, s.Col = s.pos()
  91  	s.Blank = s.line > startLine || startCol == Colbase
  92  	s.start()
  93  	if IsLetter(s.ch) || s.ch >= utf8.RuneSelf && s.AtIdentChar(true) {
  94  		s.nextch()
  95  		s.Ident()
  96  		return
  97  	}
  98  
  99  	switch s.ch {
 100  	case -1:
 101  		if nlsemi {
 102  			s.Lit = "EOF"
 103  			s.Tok = token.Semi
 104  			break
 105  		}
 106  		s.Tok = token.EOF
 107  
 108  	case '\n':
 109  		s.nextch()
 110  		s.Lit = "newline"
 111  		s.Tok = token.Semi
 112  
 113  	case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
 114  		s.Number(false)
 115  
 116  	case '"':
 117  		s.stdString()
 118  
 119  	case '`':
 120  		s.rawString()
 121  
 122  	case '\'':
 123  		s.rune()
 124  
 125  	case '(':
 126  		s.nextch()
 127  		s.Tok = token.Lparen
 128  
 129  	case '[':
 130  		s.nextch()
 131  		s.Tok = token.Lbrack
 132  
 133  	case '{':
 134  		s.nextch()
 135  		s.Tok = token.Lbrace
 136  
 137  	case ',':
 138  		s.nextch()
 139  		s.Tok = token.Comma
 140  
 141  	case ';':
 142  		s.nextch()
 143  		s.Lit = "semicolon"
 144  		s.Tok = token.Semi
 145  
 146  	case ')':
 147  		s.nextch()
 148  		s.nlsemi = true
 149  		s.Tok = token.Rparen
 150  
 151  	case ']':
 152  		s.nextch()
 153  		s.nlsemi = true
 154  		s.Tok = token.Rbrack
 155  
 156  	case '}':
 157  		s.nextch()
 158  		s.nlsemi = true
 159  		s.Tok = token.Rbrace
 160  
 161  	case ':':
 162  		s.nextch()
 163  		if s.ch == '=' {
 164  			s.nextch()
 165  			s.Tok = token.Define
 166  			break
 167  		}
 168  		s.Tok = token.Colon
 169  
 170  	case '.':
 171  		s.nextch()
 172  		if IsDecimal(s.ch) {
 173  			s.Number(true)
 174  			break
 175  		}
 176  		if s.ch == '.' {
 177  			s.nextch()
 178  			if s.ch == '.' {
 179  				s.nextch()
 180  				s.Tok = token.DotDotDot
 181  				break
 182  			}
 183  			s.rewind()
 184  			s.nextch()
 185  		}
 186  		s.Tok = token.Dot
 187  
 188  	case '+':
 189  		s.nextch()
 190  		s.Op, s.Prec = token.Add, token.PrecAdd
 191  		if s.ch != '+' {
 192  			s.assignOp()
 193  			return
 194  		}
 195  		s.nextch()
 196  		s.nlsemi = true
 197  		s.Tok = token.IncOp
 198  
 199  	case '-':
 200  		s.nextch()
 201  		s.Op, s.Prec = token.Sub, token.PrecAdd
 202  		if s.ch != '-' {
 203  			s.assignOp()
 204  			return
 205  		}
 206  		s.nextch()
 207  		s.nlsemi = true
 208  		s.Tok = token.IncOp
 209  
 210  	case '*':
 211  		s.nextch()
 212  		s.Op, s.Prec = token.Mul, token.PrecMul
 213  		if s.ch == '=' {
 214  			s.nextch()
 215  			s.Tok = token.AssignOp
 216  			break
 217  		}
 218  		s.Tok = token.Star
 219  
 220  	case '/':
 221  		s.nextch()
 222  		if s.ch == '/' {
 223  			s.nextch()
 224  			s.lineComment()
 225  			goto redo
 226  		}
 227  		if s.ch == '*' {
 228  			s.nextch()
 229  			s.fullComment()
 230  			if line, _ := s.pos(); line > s.Line && nlsemi {
 231  				s.Lit = "newline"
 232  				s.Tok = token.Semi
 233  				break
 234  			}
 235  			goto redo
 236  		}
 237  		s.Op, s.Prec = token.Div, token.PrecMul
 238  		if s.ch == '=' {
 239  			s.nextch()
 240  			s.Tok = token.AssignOp
 241  		} else {
 242  			s.Tok = token.OperatorType
 243  		}
 244  
 245  	case '%':
 246  		s.nextch()
 247  		s.Op, s.Prec = token.Rem, token.PrecMul
 248  		if s.ch == '=' {
 249  			s.nextch()
 250  			s.Tok = token.AssignOp
 251  		} else {
 252  			s.Tok = token.OperatorType
 253  		}
 254  
 255  	case '&':
 256  		s.nextch()
 257  		if s.ch == '&' {
 258  			s.nextch()
 259  			s.Op, s.Prec = token.AndAnd, token.PrecAndAnd
 260  			s.Tok = token.OperatorType
 261  			break
 262  		}
 263  		s.Op, s.Prec = token.And, token.PrecMul
 264  		if s.ch == '^' {
 265  			s.nextch()
 266  			s.Op = token.AndNot
 267  		}
 268  		if s.ch == '=' {
 269  			s.nextch()
 270  			s.Tok = token.AssignOp
 271  		} else {
 272  			s.Tok = token.OperatorType
 273  		}
 274  
 275  	case '|':
 276  		s.nextch()
 277  		if s.ch == '|' {
 278  			s.nextch()
 279  			s.Op, s.Prec = token.OrOr, token.PrecOrOr
 280  			s.Tok = token.OperatorType
 281  			break
 282  		}
 283  		s.Op, s.Prec = token.Or, token.PrecAdd
 284  		if s.ch == '=' {
 285  			s.nextch()
 286  			s.Tok = token.AssignOp
 287  		} else {
 288  			s.Tok = token.OperatorType
 289  		}
 290  
 291  	case '^':
 292  		s.nextch()
 293  		s.Op, s.Prec = token.Xor, token.PrecAdd
 294  		if s.ch == '=' {
 295  			s.nextch()
 296  			s.Tok = token.AssignOp
 297  		} else {
 298  			s.Tok = token.OperatorType
 299  		}
 300  
 301  	case '<':
 302  		s.nextch()
 303  		if s.ch == '=' {
 304  			s.nextch()
 305  			s.Op, s.Prec = token.Leq, token.PrecCmp
 306  			s.Tok = token.OperatorType
 307  			break
 308  		}
 309  		if s.ch == '<' {
 310  			s.nextch()
 311  			s.Op, s.Prec = token.Shl, token.PrecMul
 312  			s.assignOp()
 313  			return
 314  		}
 315  		if s.ch == '-' {
 316  			s.nextch()
 317  			s.Tok = token.Arrow
 318  			break
 319  		}
 320  		s.Op, s.Prec = token.Lss, token.PrecCmp
 321  		s.Tok = token.OperatorType
 322  
 323  	case '>':
 324  		s.nextch()
 325  		if s.ch == '=' {
 326  			s.nextch()
 327  			s.Op, s.Prec = token.Geq, token.PrecCmp
 328  			s.Tok = token.OperatorType
 329  			break
 330  		}
 331  		if s.ch == '>' {
 332  			s.nextch()
 333  			s.Op, s.Prec = token.Shr, token.PrecMul
 334  			s.assignOp()
 335  			return
 336  		}
 337  		s.Op, s.Prec = token.Gtr, token.PrecCmp
 338  		s.Tok = token.OperatorType
 339  
 340  	case '=':
 341  		s.nextch()
 342  		if s.ch == '=' {
 343  			s.nextch()
 344  			s.Op, s.Prec = token.Eql, token.PrecCmp
 345  			s.Tok = token.OperatorType
 346  			break
 347  		}
 348  		s.Tok = token.Assign
 349  
 350  	case '!':
 351  		s.nextch()
 352  		if s.ch == '=' {
 353  			s.nextch()
 354  			s.Op, s.Prec = token.Neq, token.PrecCmp
 355  			s.Tok = token.OperatorType
 356  			break
 357  		}
 358  		s.Op, s.Prec = token.Not, 0
 359  		s.Tok = token.OperatorType
 360  
 361  	case '~':
 362  		s.nextch()
 363  		s.Op, s.Prec = token.Tilde, 0
 364  		s.Tok = token.OperatorType
 365  
 366  	default:
 367  		s.Errorf("invalid character " | fmtRuneU(s.ch))
 368  		s.nextch()
 369  		goto redo
 370  	}
 371  
 372  	return
 373  }
 374  
 375  func (s *Scanner) assignOp() {
 376  	if s.ch == '=' {
 377  		s.nextch()
 378  		s.Tok = token.AssignOp
 379  		return
 380  	}
 381  	s.Tok = token.OperatorType
 382  }
 383  
 384  func (s *Scanner) Ident() {
 385  	for IsLetter(s.ch) || IsDecimal(s.ch) {
 386  		s.nextch()
 387  	}
 388  
 389  	if s.ch >= utf8.RuneSelf {
 390  		for s.AtIdentChar(false) {
 391  			s.nextch()
 392  		}
 393  	}
 394  
 395  	lit := s.segmentCopy()
 396  	if len(lit) >= 2 {
 397  		h := (uint32(lit[0])<<4 ^ uint32(lit[1]) + uint32(len(lit))) & 63
 398  		if tok := s.keywordMap[h]; tok != 0 && tokStrFast(tok) == string(lit) {
 399  			s.nlsemi = token.Contains(1<<token.Break|1<<token.Continue|1<<token.Fallthrough|1<<token.Return, tok)
 400  			s.Tok = tok
 401  			return
 402  		}
 403  	}
 404  
 405  	s.nlsemi = true
 406  	c := []byte{:len(lit)}
 407  	copy(c, lit)
 408  	s.Lit = string(c)
 409  	s.Tok = token.NameType
 410  }
 411  
 412  func tokStrFast(tok token.Token) (s string) {
 413  	idx := [48]uint8{0, 3, 7, 14, 16, 19, 23, 24, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 47, 51, 55, 60, 68, 75, 80, 84, 95, 98, 102, 104, 108, 110, 116, 125, 128, 135, 140, 146, 152, 158, 164, 168, 171, 171}
 414  	return token.Token_name[idx[tok-1]:idx[tok]]
 415  }
 416  
 417  func (s *Scanner) AtIdentChar(first bool) (ok bool) {
 418  	switch {
 419  	case isLetter(s.ch) || s.ch == '_':
 420  	case isDigit(s.ch):
 421  		if first {
 422  			s.Errorf("identifier cannot begin with digit " | fmtRuneU(s.ch))
 423  		}
 424  	case s.ch >= utf8.RuneSelf:
 425  		s.Errorf("invalid character " | fmtRuneU(s.ch) | " in identifier")
 426  	default:
 427  		return false
 428  	}
 429  	return true
 430  }
 431  
 432  func (s *Scanner) initKeywords() {
 433  	if s.keywordsReady {
 434  		return
 435  	}
 436  	s.keywordsReady = true
 437  	for tok := token.Break; tok <= token.Var; tok++ {
 438  		b := []byte(tok.String())
 439  		h := (uint32(b[0])<<4 ^ uint32(b[1]) + uint32(len(b))) & 63
 440  		if s.keywordMap[h] != 0 {
 441  			panic("imperfect hash")
 442  		}
 443  		s.keywordMap[h] = tok
 444  	}
 445  }
 446  
 447  func Lower(ch rune) (r rune) { return ('a' - 'A') | ch }
 448  func IsLetter(ch rune) (ok bool) { return 'a' <= Lower(ch) && Lower(ch) <= 'z' || ch == '_' }
 449  func IsDecimal(ch rune) (ok bool) { return '0' <= ch && ch <= '9' }
 450  func IsHex(ch rune) (ok bool) { return '0' <= ch && ch <= '9' || 'a' <= Lower(ch) && Lower(ch) <= 'f' }
 451  
 452  func (s *Scanner) Digits(base int32, invalid *int32) (digsep int32) {
 453  	if base <= 10 {
 454  		hi := rune('0' + base)
 455  		for IsDecimal(s.ch) || s.ch == '_' {
 456  			ds := int32(1)
 457  			if s.ch == '_' {
 458  				ds = 2
 459  			} else if s.ch >= hi && *invalid < 0 {
 460  				_, col := s.pos()
 461  				*invalid = int32(col - s.col)
 462  			}
 463  			digsep |= ds
 464  			s.nextch()
 465  		}
 466  	} else {
 467  		for IsHex(s.ch) || s.ch == '_' {
 468  			ds := int32(1)
 469  			if s.ch == '_' {
 470  				ds = 2
 471  			}
 472  			digsep |= ds
 473  			s.nextch()
 474  		}
 475  	}
 476  	return
 477  }
 478  
 479  func (s *Scanner) Number(seenPoint bool) {
 480  	ok := true
 481  	kind := token.IntLit
 482  	base := int32(10)
 483  	prefix := rune(0)
 484  	digsep := int32(0)
 485  	invalid := int32(-1)
 486  
 487  	if !seenPoint {
 488  		if s.ch == '0' {
 489  			s.nextch()
 490  			switch Lower(s.ch) {
 491  			case 'x':
 492  				s.nextch()
 493  				base, prefix = 16, 'x'
 494  			case 'o':
 495  				s.nextch()
 496  				base, prefix = 8, 'o'
 497  			case 'b':
 498  				s.nextch()
 499  				base, prefix = 2, 'b'
 500  			default:
 501  				base, prefix = 8, '0'
 502  				digsep = 1
 503  			}
 504  		}
 505  		digsep |= s.Digits(base, &invalid)
 506  		if s.ch == '.' {
 507  			if prefix == 'o' || prefix == 'b' {
 508  				s.Errorf("invalid radix point in " | baseName(base) | " literal")
 509  				ok = false
 510  			}
 511  			s.nextch()
 512  			seenPoint = true
 513  		}
 514  	}
 515  
 516  	if seenPoint {
 517  		kind = token.FloatLit
 518  		digsep |= s.Digits(base, &invalid)
 519  	}
 520  
 521  	if digsep&1 == 0 && ok {
 522  		s.Errorf(baseName(base) | " literal has no digits")
 523  		ok = false
 524  	}
 525  
 526  	if e := Lower(s.ch); e == 'e' || e == 'p' {
 527  		if ok {
 528  			switch {
 529  			case e == 'e' && prefix != 0 && prefix != '0':
 530  				s.Errorf(fmtQuoteRune(s.ch) | " exponent requires decimal mantissa")
 531  				ok = false
 532  			case e == 'p' && prefix != 'x':
 533  				s.Errorf(fmtQuoteRune(s.ch) | " exponent requires hexadecimal mantissa")
 534  				ok = false
 535  			}
 536  		}
 537  		s.nextch()
 538  		kind = token.FloatLit
 539  		if s.ch == '+' || s.ch == '-' {
 540  			s.nextch()
 541  		}
 542  		digsep = s.Digits(10, nil) | digsep&2
 543  		if digsep&1 == 0 && ok {
 544  			s.Errorf("exponent has no digits")
 545  			ok = false
 546  		}
 547  	} else if prefix == 'x' && kind == token.FloatLit && ok {
 548  		s.Errorf("hexadecimal mantissa requires a 'p' exponent")
 549  		ok = false
 550  	}
 551  
 552  	if s.ch == 'i' {
 553  		kind = token.ImagLit
 554  		s.nextch()
 555  	}
 556  
 557  	s.SetLit(kind, ok)
 558  
 559  	if kind == token.IntLit && invalid >= 0 && ok {
 560  		s.ErrorAtf(invalid, "invalid digit " | fmtQuoteRune(rune(s.Lit[invalid])) | " in " | baseName(base) | " literal")
 561  		ok = false
 562  	}
 563  
 564  	if digsep&2 != 0 && ok {
 565  		if i := invalidSep(s.Lit); i >= 0 {
 566  			s.ErrorAtf(i, "'_' must separate successive digits")
 567  			ok = false
 568  		}
 569  	}
 570  
 571  	s.Bad = !ok
 572  }
 573  
 574  func baseName(base int32) (s string) {
 575  	switch base {
 576  	case 2:
 577  		return "binary"
 578  	case 8:
 579  		return "octal"
 580  	case 10:
 581  		return "decimal"
 582  	case 16:
 583  		return "hexadecimal"
 584  	}
 585  	panic("invalid base")
 586  }
 587  
 588  func invalidSep(x string) (n int32) {
 589  	x1 := ' '
 590  	d := '.'
 591  	i := int32(0)
 592  
 593  	if len(x) >= 2 && x[0] == '0' {
 594  		x1 = Lower(rune(x[1]))
 595  		if x1 == 'x' || x1 == 'o' || x1 == 'b' {
 596  			d = '0'
 597  			i = 2
 598  		}
 599  	}
 600  
 601  	for ; i < int32(len(x)); i++ {
 602  		p := d
 603  		d = rune(x[i])
 604  		switch {
 605  		case d == '_':
 606  			if p != '0' {
 607  				return i
 608  			}
 609  		case IsDecimal(d) || x1 == 'x' && IsHex(d):
 610  			d = '0'
 611  		default:
 612  			if p == '_' {
 613  				return i - 1
 614  			}
 615  			d = '.'
 616  		}
 617  	}
 618  	if d == '_' {
 619  		return int32(len(x)) - 1
 620  	}
 621  
 622  	return -1
 623  }
 624  
 625  func (s *Scanner) rune() {
 626  	ok := true
 627  	s.nextch()
 628  
 629  	n := 0
 630  	for ; ; n++ {
 631  		if s.ch == '\'' {
 632  			if ok {
 633  				if n == 0 {
 634  					s.Errorf("empty rune literal or unescaped '")
 635  					ok = false
 636  				} else if n != 1 {
 637  					s.ErrorAtf(0, "more than one character in rune literal")
 638  					ok = false
 639  				}
 640  			}
 641  			s.nextch()
 642  			break
 643  		}
 644  		if s.ch == '\\' {
 645  			s.nextch()
 646  			if !s.escape('\'') {
 647  				ok = false
 648  			}
 649  			continue
 650  		}
 651  		if s.ch == '\n' {
 652  			if ok {
 653  				s.Errorf("newline in rune literal")
 654  				ok = false
 655  			}
 656  			break
 657  		}
 658  		if s.ch < 0 {
 659  			if ok {
 660  				s.ErrorAtf(0, "rune literal not terminated")
 661  				ok = false
 662  			}
 663  			break
 664  		}
 665  		s.nextch()
 666  	}
 667  
 668  	s.SetLit(token.RuneLit, ok)
 669  }
 670  
 671  func (s *Scanner) stdString() {
 672  	ok := true
 673  	s.nextch()
 674  
 675  	for {
 676  		if s.ch == '"' {
 677  			s.nextch()
 678  			break
 679  		}
 680  		if s.ch == '\\' {
 681  			s.nextch()
 682  			if !s.escape('"') {
 683  				ok = false
 684  			}
 685  			continue
 686  		}
 687  		if s.ch == '\n' {
 688  			s.Errorf("newline in string")
 689  			ok = false
 690  			break
 691  		}
 692  		if s.ch < 0 {
 693  			s.ErrorAtf(0, "string not terminated")
 694  			ok = false
 695  			break
 696  		}
 697  		s.nextch()
 698  	}
 699  
 700  	s.SetLit(token.StringLit, ok)
 701  }
 702  
 703  func (s *Scanner) rawString() {
 704  	ok := true
 705  	s.nextch()
 706  
 707  	for {
 708  		if s.ch == '`' {
 709  			s.nextch()
 710  			break
 711  		}
 712  		if s.ch < 0 {
 713  			s.ErrorAtf(0, "string not terminated")
 714  			ok = false
 715  			break
 716  		}
 717  		s.nextch()
 718  	}
 719  
 720  	s.SetLit(token.StringLit, ok)
 721  }
 722  
 723  func (s *Scanner) comment(text string) {
 724  	s.ErrorAtf(0, text)
 725  }
 726  
 727  func (s *Scanner) skipLine() {
 728  	for s.ch >= 0 && s.ch != '\n' {
 729  		s.nextch()
 730  	}
 731  }
 732  
 733  func (s *Scanner) lineComment() {
 734  	if s.mode&comments != 0 {
 735  		s.skipLine()
 736  		s.comment(string(s.segmentCopy()))
 737  		return
 738  	}
 739  
 740  	if s.mode&directives == 0 || (s.ch != 'g' && s.ch != 'l') {
 741  		s.stop()
 742  		s.skipLine()
 743  		return
 744  	}
 745  
 746  	prefix := "go:"
 747  	if s.ch == 'l' {
 748  		prefix = "line "
 749  	}
 750  
 751  	for _, r := range prefix {
 752  		if s.ch != rune(r) {
 753  			s.stop()
 754  			s.skipLine()
 755  			return
 756  		}
 757  		s.nextch()
 758  	}
 759  	s.skipLine()
 760  	s.comment(string(s.segmentCopy()))
 761  }
 762  
 763  func (s *Scanner) skipComment() (ok bool) {
 764  	for s.ch >= 0 {
 765  		for s.ch == '*' {
 766  			s.nextch()
 767  			if s.ch == '/' {
 768  				s.nextch()
 769  				return true
 770  			}
 771  		}
 772  		s.nextch()
 773  	}
 774  	s.ErrorAtf(0, "comment not terminated")
 775  	return false
 776  }
 777  
 778  func (s *Scanner) fullComment() {
 779  	if s.mode&comments != 0 {
 780  		if s.skipComment() {
 781  			s.comment(string(s.segmentCopy()))
 782  		}
 783  		return
 784  	}
 785  
 786  	if s.mode&directives == 0 || s.ch != 'l' {
 787  		s.stop()
 788  		s.skipComment()
 789  		return
 790  	}
 791  
 792  	const prefix = "line "
 793  
 794  	for _, r := range prefix {
 795  		if s.ch != rune(r) {
 796  			s.stop()
 797  			s.skipComment()
 798  			return
 799  		}
 800  		s.nextch()
 801  	}
 802  	if s.skipComment() {
 803  		s.comment(string(s.segmentCopy()))
 804  	}
 805  }
 806  
 807  func (s *Scanner) escape(quote rune) (ok bool) {
 808  	var n int32
 809  	var base, maxVal uint32
 810  
 811  	switch s.ch {
 812  	case quote, 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\':
 813  		s.nextch()
 814  		return true
 815  	case '0', '1', '2', '3', '4', '5', '6', '7':
 816  		n, base, maxVal = 3, 8, 255
 817  	case 'x':
 818  		s.nextch()
 819  		n, base, maxVal = 2, 16, 255
 820  	case 'u':
 821  		s.nextch()
 822  		n, base, maxVal = 4, 16, maxRune
 823  	case 'U':
 824  		s.nextch()
 825  		n, base, maxVal = 8, 16, maxRune
 826  	default:
 827  		if s.ch < 0 {
 828  			return true
 829  		}
 830  		s.Errorf("unknown escape")
 831  		return false
 832  	}
 833  
 834  	var x uint32
 835  	for i := n; i > 0; i-- {
 836  		if s.ch < 0 {
 837  			return true
 838  		}
 839  		d := base
 840  		if IsDecimal(s.ch) {
 841  			d = uint32(s.ch) - '0'
 842  		} else if 'a' <= Lower(s.ch) && Lower(s.ch) <= 'f' {
 843  			d = uint32(Lower(s.ch)) - 'a' + 10
 844  		}
 845  		if d >= base {
 846  			s.Errorf("invalid character " | fmtQuoteRune(s.ch) | " in " | baseName(int32(base)) | " escape")
 847  			return false
 848  		}
 849  		x = x*base + d
 850  		s.nextch()
 851  	}
 852  
 853  	if x > maxVal && base == 8 {
 854  		s.Errorf("octal escape value " | token.SimpleItoaU32(x) | " > 255")
 855  		return false
 856  	}
 857  
 858  	if x > maxVal || 0xD800 <= x && x < 0xE000 {
 859  		s.Errorf("escape is invalid Unicode code point " | fmtRuneU(rune(x)))
 860  		return false
 861  	}
 862  
 863  	return true
 864  }
 865  
 866  func String(n Node) (s string) {
 867  	switch n.(type) {
 868  	case *Name:
 869  		return "Name"
 870  	case *BasicLit:
 871  		return "BasicLit"
 872  	case *CompositeLit:
 873  		return "CompositeLit"
 874  	case *FuncLit:
 875  		return "FuncLit"
 876  	case *ParenExpr:
 877  		return "ParenExpr"
 878  	case *SelectorExpr:
 879  		return "SelectorExpr"
 880  	case *IndexExpr:
 881  		return "IndexExpr"
 882  	case *SliceExpr:
 883  		return "SliceExpr"
 884  	case *AssertExpr:
 885  		return "AssertExpr"
 886  	case *TypeSwitchGuard:
 887  		return "TypeSwitchGuard"
 888  	case *Operation:
 889  		return "Operation"
 890  	case *CallExpr:
 891  		return "CallExpr"
 892  	case *ListExpr:
 893  		return "ListExpr"
 894  	case *ArrayType:
 895  		return "ArrayType"
 896  	case *SliceType:
 897  		return "SliceType"
 898  	case *DotsType:
 899  		return "DotsType"
 900  	case *StructType:
 901  		return "StructType"
 902  	case *InterfaceType:
 903  		return "InterfaceType"
 904  	case *FuncType:
 905  		return "FuncType"
 906  	case *ChanType:
 907  		return "ChanType"
 908  	case *MapType:
 909  		return "MapType"
 910  	case *BadExpr:
 911  		return "BadExpr"
 912  	case *EmptyStmt:
 913  		return "EmptyStmt"
 914  	case *LabeledStmt:
 915  		return "LabeledStmt"
 916  	case *BlockStmt:
 917  		return "BlockStmt"
 918  	case *ExprStmt:
 919  		return "ExprStmt"
 920  	case *SendStmt:
 921  		return "SendStmt"
 922  	case *DeclStmt:
 923  		return "DeclStmt"
 924  	case *AssignStmt:
 925  		return "AssignStmt"
 926  	case *BranchStmt:
 927  		return "BranchStmt"
 928  	case *CallStmt:
 929  		return "CallStmt"
 930  	case *ReturnStmt:
 931  		return "ReturnStmt"
 932  	case *IfStmt:
 933  		return "IfStmt"
 934  	case *ForStmt:
 935  		return "ForStmt"
 936  	case *SwitchStmt:
 937  		return "SwitchStmt"
 938  	case *SelectStmt:
 939  		return "SelectStmt"
 940  	case *RangeClause:
 941  		return "RangeClause"
 942  	case *CaseClause:
 943  		return "CaseClause"
 944  	case *CommClause:
 945  		return "CommClause"
 946  	case *ImportDecl:
 947  		return "ImportDecl"
 948  	case *ConstDecl:
 949  		return "ConstDecl"
 950  	case *TypeDecl:
 951  		return "TypeDecl"
 952  	case *VarDecl:
 953  		return "VarDecl"
 954  	case *FuncDecl:
 955  		return "FuncDecl"
 956  	case *File:
 957  		return "File"
 958  	}
 959  	return "Node"
 960  }
 961  
 962  func StartPos(n Node) (p token.Pos) {
 963  	return n.Pos()
 964  }
 965  
 966  // fmtRuneU formats a rune as "U+XXXX 'c'" (like %#U).
 967  func fmtRuneU(r rune) (s string) {
 968  	hex := fmtHex32(uint32(r))
 969  	s = "U+" | hex
 970  	if r >= 0x20 && r < 0x7f {
 971  		s = s | " '" | string([]byte{byte(r)}) | "'"
 972  	}
 973  	return s
 974  }
 975  
 976  // fmtQuoteRune formats a rune as 'c' (like %q for rune).
 977  func fmtQuoteRune(r rune) (s string) {
 978  	if r >= 0x20 && r < 0x7f {
 979  		return "'" | string([]byte{byte(r)}) | "'"
 980  	}
 981  	return "U+" | fmtHex32(uint32(r))
 982  }
 983  
 984  // fmtHex32 formats a uint32 as uppercase hex with at least 4 digits.
 985  func fmtHex32(v uint32) (s string) {
 986  	const digits = "0123456789ABCDEF"
 987  	buf := []byte{:0:8}
 988  	if v == 0 {
 989  		return "0000"
 990  	}
 991  	for v > 0 {
 992  		push(buf, digits[v&0xf])
 993  		v >>= 4
 994  	}
 995  	for len(buf) < 4 {
 996  		push(buf, '0')
 997  	}
 998  	for i, j := int32(0), len(buf)-1; i < j; i, j = i+1, j-1 {
 999  		buf[i], buf[j] = buf[j], buf[i]
1000  	}
1001  	return string(buf)
1002  }
1003