scanner.mx raw

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