arg := make([]rune, len(s))
escaped := false
quoted := false
- quote := rune(0)
+ quote := '\x00'
i := 0
for _, r := range s {
switch {
func firstSentence(s string) string {
i := -1 // index+1 of first terminator (punctuation ending a sentence)
j := -1 // index+1 of first terminator followed by white space
- prev := rune('A')
+ prev := 'A'
for k, ch := range s {
k1 := k + 1
if ch == '.' || ch == '!' || ch == '?' {
// Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling
// the closure once per rune.
- prev := rune(' ')
+ prev := ' '
return Map(
func(r rune) rune {
if isSeparator(prev) {
func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
p.scanner.Init(src)
p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
- p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+ p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
p.scanner.Whitespace = 1<<'\t' | 1<<' '
p.scanner.Filename = filename // for good error messages
p.next()
}
func (p *gcParser) expectSpecial(tok string) {
- sep := rune('x') // not white space
+ sep := 'x' // not white space
i := 0
for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
func (p *gcParser) parseDotIdent() string {
ident := ""
if p.tok != scanner.Int {
- sep := rune('x') // not white space
+ sep := 'x' // not white space
for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == 'ยท') && sep > ' ' {
ident += p.lit
sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
// Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit .
// bool_lit = "true" | "false" .
// complex_lit = "(" float_lit "+" float_lit ")" .
+// rune_lit = "(" int_lit "+" int_lit ")" .
// string_lit = `"` { unicode_char } `"` .
//
func (p *gcParser) parseConstDecl() {
typ = Float64.Underlying
}
case '(':
- // complex_lit
+ // complex_lit or rune_lit
p.next()
+ if p.tok == scanner.Char {
+ p.next()
+ p.expect('+')
+ p.parseNumber()
+ // TODO: x = ...
+ break
+ }
re := p.parseNumber()
p.expect('+')
im := p.parseNumber()
p.expect(')')
x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
typ = Complex128.Underlying
+ case scanner.Char:
+ // TODO: x = ...
+ p.next()
case scanner.String:
// string_lit
x = MakeConst(token.STRING, p.lit)
p.next()
typ = String.Underlying
default:
- p.error("expected literal")
+ println(p.tok)
+ p.errorf("expected literal got %s", scanner.TokenString(p.tok))
}
if obj.Type == nil {
obj.Type = typ
stringVal string
stringVal1 string
bytesVal []byte
+ runeVal rune
complex64Val complex64
complex128Val complex128
renamedBoolVal renamedBool
{"%v", "0377\n", &intVal, 0377},
{"%v", "0x44\n", &intVal, 0x44},
{"%d", "72\n", &intVal, 72},
- {"%c", "a\n", &intVal, 'a'},
- {"%c", "\u5072\n", &intVal, 0x5072},
- {"%c", "\u1234\n", &intVal, '\u1234'},
+ {"%c", "a\n", &runeVal, 'a'},
+ {"%c", "\u5072\n", &runeVal, '\u5072'},
+ {"%c", "\u1234\n", &runeVal, '\u1234'},
{"%d", "73\n", &int8Val, int8(73)},
{"%d", "+74\n", &int16Val, int16(74)},
{"%d", "75\n", &int32Val, int32(75)},
var c complex128
var x, y Xs
var z IntString
+var r1, r2, r3 rune
var multiTests = []ScanfMultiTest{
{"", "", []interface{}{}, []interface{}{}, ""},
{"%3d22%3d", "33322333", args(&i, &j), args(333, 333), ""},
{"%6vX=%3fY", "3+2iX=2.5Y", args(&c, &f), args((3 + 2i), 2.5), ""},
{"%d%s", "123abc", args(&i, &s), args(123, "abc"), ""},
- {"%c%c%c", "2\u50c2X", args(&i, &j, &k), args('2', '\u50c2', 'X'), ""},
+ {"%c%c%c", "2\u50c2X", args(&r1, &r2, &r3), args('2', '\u50c2', 'X'), ""},
// Custom scanners.
{"%e%f", "eefffff", args(&x, &y), args(Xs("ee"), Xs("fffff")), ""},
{"X%d", "10X", args(&intVal), nil, "input does not match format"},
// Bad UTF-8: should see every byte.
- {"%c%c%c", "\xc2X\xc2", args(&i, &j, &k), args(utf8.RuneError, 'X', utf8.RuneError), ""},
+ {"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
}
func testScan(name string, t *testing.T, scan func(r io.Reader, a ...interface{}) (int, error)) {
arg := make([]rune, len(s))
escaped := false
quoted := false
- quote := rune(0)
+ quote := '\x00'
i := 0
for _, rune := range s {
switch {
case rune == '\\':
escaped = true
continue
- case quote != 0:
+ case quote != '\x00':
if rune == quote {
- quote = 0
+ quote = '\x00'
continue
}
case rune == '"' || rune == '\'':
i++
}
- x := rune(0)
+ x := '\x00'
for i < len(s) {
c = s[i]
i++
// hexDecode decodes a short hex digit sequence: "10" -> 16.
func hexDecode(s []byte) rune {
- n := rune(0)
+ n := '\x00'
for _, c := range s {
n <<= 4
switch {
const MaxBase = 'z' - 'a' + 10 + 1 // = hexValue('z') + 1
func hexValue(ch rune) Word {
- d := MaxBase + 1 // illegal base
+ d := int(MaxBase + 1) // illegal base
switch {
case '0' <= ch && ch <= '9':
d = int(ch - '0')
// appendNegatedClass returns the result of appending the negation of the class x to the class r.
// It assumes x is clean.
func appendNegatedClass(r []rune, x []rune) []rune {
- nextLo := rune('\u0000')
+ nextLo := '\u0000'
for i := 0; i < len(x); i += 2 {
lo, hi := x[i], x[i+1]
if nextLo <= lo-1 {
// appendNegatedTable returns the result of appending the negation of x to the class r.
func appendNegatedTable(r []rune, x *unicode.RangeTable) []rune {
- nextLo := rune('\u0000') // lo end of next class to add
+ nextLo := '\u0000' // lo end of next class to add
for _, xr := range x.R16 {
lo, hi, stride := rune(xr.Lo), rune(xr.Hi), rune(xr.Stride)
if stride == 1 {
// negateClass overwrites r and returns r's negation.
// It assumes the class r is already clean.
func negateClass(r []rune) []rune {
- nextLo := rune('\u0000') // lo end of next class to add
- w := 0 // write index
+ nextLo := '\u0000' // lo end of next class to add
+ w := 0 // write index
for i := 0; i < len(r); i += 2 {
lo, hi := r[i], r[i+1]
if nextLo <= lo-1 {
// Use a closure here to remember state.
// Hackish but effective. Depends on Map scanning in order and calling
// the closure once per rune.
- prev := rune(' ')
+ prev := ' '
return Map(
func(r rune) rune {
if isSeparator(prev) {
func TestCaseConsistency(t *testing.T) {
// Make a string of all the runes.
- numRunes := unicode.MaxRune + 1
+ numRunes := int(unicode.MaxRune + 1)
if testing.Short() {
numRunes = 1000
}
package unicode
const (
- MaxRune = 0x10FFFF // Maximum valid Unicode code point.
- ReplacementChar = 0xFFFD // Represents invalid code points.
- MaxASCII = 0x7F // maximum ASCII value.
- MaxLatin1 = 0xFF // maximum Latin-1 value.
+ MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
+ ReplacementChar = '\uFFFD' // Represents invalid code points.
+ MaxASCII = '\u007F' // maximum ASCII value.
+ MaxLatin1 = '\u00FF' // maximum Latin-1 value.
)
// RangeTable defines a set of Unicode code points by listing the ranges of