// ParseNumber parses and returns a positive integer. // Leading spaces are ignored. // If EOF is reached before any digits are encountered, 1 is returned. func parseNumber(rs io.RuneScanner) (int, error) { if err := skipSpace(rs); err != nil { return 0, err } var s string for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: break case err != nil: return 0, err case unicode.IsDigit(r): s += string(r) continue default: if err := rs.UnreadRune(); err != nil { return 0, err } } if len(s) == 0 { return 1, nil } return strconv.Atoi(s) } }
func parseCompoundAddr(rs io.RuneScanner) (Address, error) { var a1 Address for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return a1, nil case err != nil: return nil, err case strings.ContainsRune(simpleFirst, r): if err := rs.UnreadRune(); err != nil { return nil, err } switch a2, err := parseSimpleAddr(rs); { case err != nil: return nil, err case a1 != nil: a1 = a1.Plus(a2) default: a1 = a2 } case r == '+' || r == '-': if a1 == nil { a1 = Dot } a2, err := parseSimpleAddr(rs) if a2 == nil { a2 = Line(1) } switch { case err != nil: return nil, err case r == '+': a1 = a1.Plus(a2) default: a1 = a1.Minus(a2) } case r == ',' || r == ';': if a1 == nil { a1 = Line(0) } a2, err := parseCompoundAddr(rs) if a2 == nil { a2 = End } switch { case err != nil: return nil, err case r == ',': a1 = a1.To(a2) default: a1 = a1.Then(a2) } case unicode.IsSpace(r) && r != '\n': continue default: return a1, rs.UnreadRune() } } }
func chompBOM(r io.RuneScanner) (err error) { for { c, _, err := r.ReadRune() if err != nil { return err } if c != BOM { r.UnreadRune() return nil } } }
func chompWhitespace(r io.RuneScanner) (err error) { for { c, _, err := r.ReadRune() if err != nil { return err } if !unicode.IsSpace(c) { r.UnreadRune() return nil } } }
func skipSingleNewline(rs io.RuneScanner) error { // Eat a single trailing newline. switch r, _, err := rs.ReadRune(); { case err == io.EOF: return nil case err != nil: return err case r == '\n': return nil default: return rs.UnreadRune() } }
func readNumber(b int, r io.RuneScanner) string { s := string(b) rune, _, err := r.ReadRune() for err == nil && string(rune) != " " && string(rune) != "(" && string(rune) != ")" { s = s + string(rune) rune, _, err = r.ReadRune() } if err == nil { r.UnreadRune() } return s }
// SkipSpace consumes and ignores non-newline whitespace. // Terminates if a newline is encountered. // The terminating newline remains consumed. func skipSpace(rs io.RuneScanner) error { for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return nil case err != nil: return err case r != '\n' && unicode.IsSpace(r): continue default: return rs.UnreadRune() } } }
// readSdParam reads a PARAM-NAME as defined by RFC-5424 // SD-PARAM = PARAM-NAME "=" %d34 PARAM-VALUE %d34 // PARAM-NAME = SD-NAME // SD-NAME = 1*32PRINTUSASCII except '=', SP, ']', %d34 (") func readSdParamName(r io.RuneScanner) (string, error) { rv := &bytes.Buffer{} for { ch, _, err := r.ReadRune() if err != nil { return "", err } if ch == '=' { r.UnreadRune() return string(rv.Bytes()), nil } rv.WriteRune(ch) } }
func parseNegation(r io.RuneScanner, glob *globImpl) error { for { char, _, err := r.ReadRune() if err != nil { return err } else if char == '!' { glob.negated = !glob.negated } else { r.UnreadRune() return nil } } }
func readword(f *Xfile, isnum bool) string { var ( barr [512]rune sp int c rune err error sc io.RuneScanner ) if f.isgraphic() { sc = f.graph } else { sc = f.b } buf := barr[0:0] sp = 0 for { c, _, err = sc.ReadRune() if err!=nil || !unicode.IsSpace(c) { break } } for { if err!=nil && sp==0 { panic("read: eof met") } buf = append(buf, c) sp++ c, _, err = sc.ReadRune() if err!=nil || (isnum && !strings.ContainsRune("0123456789+-eE.", c)) { break } if err!=nil || unicode.IsSpace(c) { break } } if err != nil { if iseof(c, err) { f.eof = true } } else { f.eol = (c == rune(paminstr.EOL[0])) if !f.eol { sc.UnreadRune() } } if len(buf) == 0 { panic("read: eof met") } return string(buf) }
func readNumber(b int, r io.RuneScanner) interface{} { s := string(b) for { rune := readRune(r) if rune == -1 || isWhiteSpace(rune) || rune == ')' { r.UnreadRune() return s } s = s + string(rune) } return matchNumer(s) }
func scanDigits(rs io.RuneScanner) (string, error) { var s string for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return s, nil case err != nil: return "", err case !unicode.IsDigit(r): return s, rs.UnreadRune() default: s += string(r) } } }
func ScanDelimited(r io.RuneScanner, start, end rune, escapes map[rune]rune, escapesPassThru bool) ([]byte, error) { // Scan start delimiter. if ch, _, err := r.ReadRune(); err != nil { return nil, err } else if ch != start { return nil, fmt.Errorf("expected %s; found %s", string(start), string(ch)) } var buf bytes.Buffer for { ch0, _, err := r.ReadRune() if ch0 == end { return buf.Bytes(), nil } else if err != nil { return buf.Bytes(), err } else if ch0 == '\n' { return nil, errors.New("delimited text contains new line") } else if ch0 == '\\' { // If the next character is an escape then write the escaped char. // If it's not a valid escape then return an error. ch1, _, err := r.ReadRune() if err != nil { return nil, err } c, ok := escapes[ch1] if !ok { if escapesPassThru { // Unread ch1 (char after the \) _ = r.UnreadRune() // Write ch0 (\) to the output buffer. _, _ = buf.WriteRune(ch0) continue } else { buf.Reset() _, _ = buf.WriteRune(ch0) _, _ = buf.WriteRune(ch1) return buf.Bytes(), errBadEscape } } _, _ = buf.WriteRune(c) } else { _, _ = buf.WriteRune(ch0) } } }
func seqReader(rune int, r io.RuneScanner) interface{} { seq := make([]interface{}, 0) for { nrune, _, err := r.ReadRune() for isWhiteSpace(nrune) { nrune, _, err = r.ReadRune() } if err != nil || string(nrune) == ")" { return seq } r.UnreadRune() fmt.Println(seq) seq = append(seq, read(r)) } return seq }
// ScanBareIdent reads bare identifier from a rune reader. func ScanBareIdent(r io.RuneScanner) string { // Read every ident character into the buffer. // Non-ident characters and EOF will cause the loop to exit. var buf bytes.Buffer for { ch, _, err := r.ReadRune() if err != nil { break } else if !isIdentChar(ch) { r.UnreadRune() break } else { _, _ = buf.WriteRune(ch) } } return buf.String() }
// readWord reads `r` until it encounters a space (0x20) func readWord(r io.RuneScanner) (string, error) { rv := &bytes.Buffer{} for { ch, _, err := r.ReadRune() if err != nil { return "", err } else if ch != ' ' { rv.WriteRune(ch) } else { r.UnreadRune() rvString := string(rv.Bytes()) if rvString == "-" { rvString = "" } return rvString, nil } } }
func ReadList(in io.RuneScanner) Sexper { ch, _, _ := ReadChar(in) chstr := string(ch) switch chstr { case ")": return NIL case ".": list := ReadList(in) if list == NIL || fn_cdr(list) != NIL { panic(ERROR_DOT) } return fn_car(list) default: in.UnreadRune() scar := ReadSexp(in) scdr := ReadList(in) return List{scar, scdr} } }
// Decode decodes one ANSI terminal command from s. // // s should be connected to a client program that expects an // ANSI terminal on the other end. It will push bytes to us that we are meant // to intepret as terminal control codes, or text to place onto the terminal. // // This Command alone does not actually update the terminal. You need to pass // it to VT100.Process(). // // You should not share s with any other reader, because it could leave // the stream in an invalid state. func Decode(s io.RuneScanner) (Command, error) { r, size, err := s.ReadRune() if err != nil { return nil, err } if r == unicode.ReplacementChar && size == 1 { return nil, fmt.Errorf("non-utf8 data from reader") } if r == escape || r == monogramCsi { // At beginning of escape sequence. s.UnreadRune() return scanEscapeCommand(s) } if unicode.IsControl(r) { return controlCommand(r), nil } return runeCommand(r), nil }
func ReadSexp(in io.RuneScanner) Sexper { ch, _, _ := ReadChar(in) switch string(ch) { case "\"": return ReadString(in) case "(": return ReadList(in) case "'": return fn_cons(Atom{"quote"}, fn_cons(ReadSexp(in), NIL)) case ")": panic("unexcepted ')' found") default: in.UnreadRune() if unicode.IsDigit(ch) { return ReadNumber(in) } else { return ReadAtom(in) } } }
// readStructuredData reads a STRUCTURED-DATA (as defined in RFC-5424) // from `r` and assigns the StructuredData member. // // STRUCTURED-DATA = NILVALUE / 1*SD-ELEMENT // SD-ELEMENT = "[" SD-ID *(SP SD-PARAM) "]" // SD-PARAM = PARAM-NAME "=" %d34 PARAM-VALUE %d34 // SD-ID = SD-NAME // PARAM-NAME = SD-NAME // PARAM-VALUE = UTF-8-STRING ; characters '"', '\' and ']' MUST be escaped. // SD-NAME = 1*32PRINTUSASCII except '=', SP, ']', %d34 (") func (m *Message) readStructuredData(r io.RuneScanner) (err error) { m.StructuredData = []StructuredData{} ch, _, err := r.ReadRune() if err != nil { return err } if ch == '-' { return nil } r.UnreadRune() for { ch, _, err := r.ReadRune() if err == io.EOF { return nil } else if err != nil { return err // hard to reach without underlying IO error } else if ch == ' ' { r.UnreadRune() return nil } else if ch == '[' { r.UnreadRune() sde, err := readSDElement(r) if err != nil { return err } m.StructuredData = append(m.StructuredData, sde) } else { return BadFormat("StructuredData") } } }
func ReadNumber(in io.RuneScanner) Sexper { ch, _, err := ReadChar(in) chstr := string(ch) if err != nil { panic(err) } result := 0 for unicode.IsDigit(ch) && err == nil && chstr != "(" && chstr != ")" { number, _ := strconv.Atoi(string(ch)) result = result*10 + number ch, _, err = in.ReadRune() chstr = string(ch) } if err != nil && err != io.EOF { panic(err) } if chstr == "(" || chstr == ")" { in.UnreadRune() } return Number{result} }
// sexp reader func ReadAtom(in io.RuneScanner) Sexper { ch, _, err := ReadChar(in) chstr := string(ch) if err == io.EOF { panic(ERROR_EOF) } buffer := make([]rune, 128) var i int for i = 0; !unicode.IsSpace(ch) && err == nil && chstr != "(" && chstr != ")"; i++ { buffer[i] = ch ch, _, err = in.ReadRune() chstr = string(ch) } if err != nil && err != io.EOF { panic(err) } if chstr == "(" || chstr == ")" { in.UnreadRune() } return Atom{string(buffer[0:i])} }
func parseSimpleAddr(rs io.RuneScanner) (SimpleAddress, error) { for { var r rune var err error var a SimpleAddress switch r, _, err = rs.ReadRune(); { case err == io.EOF: return a, nil case err != nil: return nil, err case r == '\'': a, err = parseMarkAddr(rs) case r == '#': a, err = parseRuneAddr(rs) case strings.ContainsRune(digits, r): a, err = parseLineAddr(r, rs) case r == '/' || r == '?': if err := rs.UnreadRune(); err != nil { return nil, err } exp, err := parseRegexp2(rs) if err != nil { return nil, err } return Regexp(string(exp)), nil case r == '$': a = End case r == '.': a = Dot case unicode.IsSpace(r) && r != '\n': break // nothing to do default: return nil, rs.UnreadRune() } if a != nil || err != nil { return a, err } } }
// scan sets z to the integer value corresponding to the longest possible prefix // read from r representing a signed integer number in a given conversion base. // It returns z, the actual conversion base used, and an error, if any. In the // error case, the value of z is undefined but the returned value is nil. The // syntax follows the syntax of integer literals in Go. // // The base argument must be 0 or a value from 2 through MaxBase. If the base // is 0, the string prefix determines the actual conversion base. A prefix of // ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a // ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. // func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, os.Error) { // determine sign ch, _, err := r.ReadRune() if err != nil { return nil, 0, err } neg := false switch ch { case '-': neg = true case '+': // nothing to do default: r.UnreadRune() } // determine mantissa z.abs, base, err = z.abs.scan(r, base) if err != nil { return nil, base, err } z.neg = len(z.abs) > 0 && neg // 0 has no sign return z, base, nil }
func (d *Dec) scan(r io.RuneScanner) error { d.coef.hi = 0 d.coef.lo = 0 d.scale = 0 ch, _, err := r.ReadRune() if err != nil { return err } var neg bool switch ch { case '-': neg = true case '+': default: r.UnreadRune() } var dec bool for { ch, _, err = r.ReadRune() if err == io.EOF { goto ExitLoop } if err != nil { return err } switch { case ch == '.': if dec { r.UnreadRune() goto ExitLoop } dec = true case ch >= '0' && ch <= '9': d.coef.Mul(&d.coef, intTen) var z Int128 z.SetInt64(int64(ch - '0')) d.coef.Add(&d.coef, &z) if dec { d.scale++ } default: r.UnreadRune() goto ExitLoop } } ExitLoop: if neg { d.Neg(d) } return nil }
func (z *Dec) scan(r io.RuneScanner) (*Dec, error) { unscaled := make([]byte, 0, 256) // collects chars of unscaled as bytes dp, dg := -1, -1 // indexes of decimal point, first digit loop: for { ch, _, err := r.ReadRune() if err == io.EOF { break loop } if err != nil { return nil, err } switch { case ch == '+' || ch == '-': if len(unscaled) > 0 || dp >= 0 { // must be first character r.UnreadRune() break loop } case ch == '.': if dp >= 0 { r.UnreadRune() break loop } dp = len(unscaled) continue // don't add to unscaled case ch >= '0' && ch <= '9': if dg == -1 { dg = len(unscaled) } default: r.UnreadRune() break loop } unscaled = append(unscaled, byte(ch)) } if dg == -1 { return nil, fmt.Errorf("no digits read") } if dp >= 0 { z.SetScale(Scale(len(unscaled) - dp)) } else { z.SetScale(0) } _, ok := z.UnscaledBig().SetString(string(unscaled), 10) if !ok { return nil, fmt.Errorf("invalid decimal: %s", string(unscaled)) } return z, nil }
// scan sets z to the natural number corresponding to the longest possible prefix // read from r representing an unsigned integer in a given conversion base. // It returns z, the actual conversion base used, and an error, if any. In the // error case, the value of z is undefined. The syntax follows the syntax of // unsigned integer literals in Go. // // The base argument must be 0 or a value from 2 through MaxBase. If the base // is 0, the string prefix determines the actual conversion base. A prefix of // ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a // ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10. // func (z nat) scan(r io.RuneScanner, base int) (nat, int, error) { // reject illegal bases if base < 0 || base == 1 || MaxBase < base { return z, 0, errors.New("illegal number base") } // one char look-ahead ch, _, err := r.ReadRune() if err != nil { return z, 0, err } // determine base if necessary b := Word(base) if base == 0 { b = 10 if ch == '0' { switch ch, _, err = r.ReadRune(); err { case nil: b = 8 switch ch { case 'x', 'X': b = 16 case 'b', 'B': b = 2 } if b == 2 || b == 16 { if ch, _, err = r.ReadRune(); err != nil { return z, 0, err } } case io.EOF: return z.make(0), 10, nil default: return z, 10, err } } } // convert string // - group as many digits d as possible together into a "super-digit" dd with "super-base" bb // - only when bb does not fit into a word anymore, do a full number mulAddWW using bb and dd z = z.make(0) bb := Word(1) dd := Word(0) for max := _M / b; ; { d := hexValue(ch) if d >= b { r.UnreadRune() // ch does not belong to number anymore break } if bb <= max { bb *= b dd = dd*b + d } else { // bb * b would overflow z = z.mulAddWW(z, bb, dd) bb = b dd = d } if ch, _, err = r.ReadRune(); err != nil { if err != io.EOF { return z, int(b), err } break } } switch { case bb > 1: // there was at least one mantissa digit z = z.mulAddWW(z, bb, dd) case base == 0 && b == 8: // there was only the octal prefix 0 (possibly followed by digits > 7); // return base 10, not 8 return z, 10, nil case base != 0 || b != 8: // there was neither a mantissa digit nor the octal prefix 0 return z, int(b), errors.New("syntax error scanning number") } return z.norm(), int(b), nil }
// Compile will "compile" a string literal, which it pulls from the io.RunScanner, into // the value the string literal represents. // // It returns both the value of the string literal and the original string literal code. // // If there is a syntax error in the string literal, it will return an error of type // strlit.SyntaxErrorComplainer. // // If your string literal is in a Go string, and you want to pass it to strlit.Compile(), // then wrap it in a strings.NewReader(). For example: // // compiled, code, err := strlit.Compile( strings.NewReader("‘apple banana cherry’") ) func Compile(runeScanner io.RuneScanner) (valueOfStringLiteral Parcel, stringLiteralCode Parcel, err error) { code := newParcel() var r rune // Make sure there is at least one rune. r, _, err = runeScanner.ReadRune() if io.EOF == err { runeScanner.UnreadRune() return nil, nil, newSyntaxErrorComplainer("", "Hit the EOF before getting any data.") } if nil != err { return nil, nil, err } // Make sure the first rune is a valid begin quote rune. var endRune rune switch r { case '\'': endRune = r case '"': endRune = r case '‘': endRune = '’' case '“': endRune = '”' case '‹': endRune = '›' case '«': endRune = '»' default: runeScanner.UnreadRune() return nil, nil, newSyntaxErrorComplainer(code.String(), "Not a string literal. Beginning rune for string literal is not valid.") } code.buffer.WriteRune(r) // Make sure there are more runes in the string literal code (so that we can next check it ENDS with a quote (')). if _, _, err := runeScanner.ReadRune(); nil != err { return nil, nil, newSyntaxErrorComplainer(code.String(), "Missing ending quote (') at the end of the string literal.") } runeScanner.UnreadRune() compiled := newParcel() for { r, _, err = runeScanner.ReadRune() if io.EOF == err { return nil, nil, newSyntaxErrorComplainer(code.String(), "Hit the EOF before being able to get to end of string literal.") } if nil != err { return nil, nil, err } code.buffer.WriteRune(r) if endRune == r { r2, _, err := runeScanner.ReadRune() if io.EOF == err { return compiled, code, nil } if nil != err { return nil, nil, newSyntaxErrorComplainer(code.String(), "Something bad happened.") } if endRune != r2 { runeScanner.UnreadRune() return compiled, code, nil } else { code.buffer.WriteRune(r2) } } else if '\\' == r { r2, _, err := runeScanner.ReadRune() if nil != err { return nil, nil, newSyntaxErrorComplainer(code.String(), "Backslash (\\), by itself, in the middle of a string literal.") } code.buffer.WriteRune(r2) switch r2 { case '0': r = '\x00' //@TODO: Support octal escape notation. case 'U': r3, _, err := runeScanner.ReadRune() if nil != err { msg := "Problem after reading universal character escape sequence “\\x”." return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r3) r4, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s”.", string(r3)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r4) r5, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s%s”.", string(r3), string(r4)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r5) r6, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s%s%s”.", string(r3), string(r4), string(r5)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r6) r7, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r7) r8, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r8) r9, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r9) r10, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\x%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r10) if !(('0' <= r3 && r3 <= '9') || ('A' <= r3 && r3 <= 'F') || ('a' <= r3 && r3 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r4 && r4 <= '9') || ('A' <= r4 && r4 <= 'F') || ('a' <= r4 && r4 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r5 && r5 <= '9') || ('A' <= r5 && r5 <= 'F') || ('a' <= r5 && r5 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r6 && r6 <= '9') || ('A' <= r6 && r6 <= 'F') || ('a' <= r6 && r6 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r7 && r7 <= '9') || ('A' <= r7 && r7 <= 'F') || ('a' <= r7 && r7 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r8 && r8 <= '9') || ('A' <= r8 && r8 <= 'F') || ('a' <= r8 && r8 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r9 && r9 <= '9') || ('A' <= r9 && r9 <= 'F') || ('a' <= r9 && r9 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r10 && r10 <= '9') || ('A' <= r10 && r10 <= 'F') || ('a' <= r10 && r10 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\U%s%s%s%s%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6), string(r7), string(r8), string(r9), string(r10)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } r = 0 if '0' <= r3 && r3 <= '9' { r += (r3 - '0') * 16 * 16 * 16 * 16 * 16 * 16 * 16 } else if 'A' <= r3 && r3 <= 'F' { r += (r3 - 'A' + 10) * 16 * 16 * 16 * 16 * 16 * 16 * 16 } else if 'a' <= r3 && r3 <= 'f' { r += (r3 - 'a' + 10) * 16 * 16 * 16 * 16 * 16 * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r4 && r4 <= '9' { r += (r4 - '0') * 16 * 16 * 16 * 16 * 16 * 16 } else if 'A' <= r4 && r4 <= 'F' { r += (r4 - 'A' + 10) * 16 * 16 * 16 * 16 * 16 * 16 } else if 'a' <= r4 && r4 <= 'f' { r += (r4 - 'a' + 10) * 16 * 16 * 16 * 16 * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r5 && r5 <= '9' { r += (r5 - '0') * 16 * 16 * 16 * 16 * 16 } else if 'A' <= r5 && r5 <= 'F' { r += (r5 - 'A' + 10) * 16 * 16 * 16 * 16 * 16 } else if 'a' <= r5 && r5 <= 'f' { r += (r5 - 'a' + 10) * 16 * 16 * 16 * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r6 && r6 <= '9' { r += (r6 - '0') * 16 * 16 * 16 * 16 } else if 'A' <= r6 && r6 <= 'F' { r += (r6 - 'A' + 10) * 16 * 16 * 16 * 16 } else if 'a' <= r6 && r6 <= 'f' { r += (r6 - 'a' + 10) * 16 * 16 * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r7 && r7 <= '9' { r += (r7 - '0') * 16 * 16 * 16 } else if 'A' <= r7 && r7 <= 'F' { r += (r7 - 'A' + 10) * 16 * 16 * 16 } else if 'a' <= r7 && r7 <= 'f' { r += (r7 - 'a' + 10) * 16 * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r8 && r8 <= '9' { r += (r8 - '0') * 16 * 16 } else if 'A' <= r8 && r8 <= 'F' { r += (r8 - 'A' + 10) * 16 * 16 } else if 'a' <= r8 && r8 <= 'f' { r += (r8 - 'a' + 10) * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r9 && r9 <= '9' { r += (r9 - '0') * 16 } else if 'A' <= r9 && r9 <= 'F' { r += (r9 - 'A' + 10) * 16 } else if 'a' <= r9 && r9 <= 'f' { r += (r9 - 'a' + 10) * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r10 && r10 <= '9' { r += (r10 - '0') } else if 'A' <= r10 && r10 <= 'F' { r += (r10 - 'A' + 10) } else if 'a' <= r10 && r10 <= 'f' { r += (r10 - 'a' + 10) } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } case 'a': r = '\a' case 'b': r = '\b' case 'e': r = '\x1B' case 'f': r = '\f' case 'n': r = '\n' case 'r': r = '\r' case 't': r = '\t' case 'u': r3, _, err := runeScanner.ReadRune() if nil != err { msg := "Problem after reading hexadecimal escape “\\x”." return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r3) r4, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\u%s”.", string(r3)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r4) r5, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\u%s%s”.", string(r3), string(r4)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r5) r6, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading universal character escape sequence “\\u%s%s%s”.", string(r3), string(r4), string(r5)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r6) if !(('0' <= r3 && r3 <= '9') || ('A' <= r3 && r3 <= 'F') || ('a' <= r3 && r3 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\u%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r4 && r4 <= '9') || ('A' <= r4 && r4 <= 'F') || ('a' <= r4 && r4 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\u%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r5 && r5 <= '9') || ('A' <= r5 && r5 <= 'F') || ('a' <= r5 && r5 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\u%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r6 && r6 <= '9') || ('A' <= r6 && r6 <= 'F') || ('a' <= r6 && r6 <= 'f')) { msg := fmt.Sprintf("Invalid universal character escape sequence: “\\u%s%s%s%s”.", string(r3), string(r4), string(r5), string(r6)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } r = 0 if '0' <= r3 && r3 <= '9' { r += (r3 - '0') * 16 * 16 * 16 } else if 'A' <= r3 && r3 <= 'F' { r += (r3 - 'A' + 10) * 16 * 16 * 16 } else if 'a' <= r3 && r3 <= 'f' { r += (r3 - 'a' + 10) * 16 * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r4 && r4 <= '9' { r += (r4 - '0') * 16 * 16 } else if 'A' <= r4 && r4 <= 'F' { r += (r4 - 'A' + 10) * 16 * 16 } else if 'a' <= r4 && r4 <= 'f' { r += (r4 - 'a' + 10) * 16 * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r5 && r5 <= '9' { r += (r5 - '0') * 16 } else if 'A' <= r5 && r5 <= 'F' { r += (r5 - 'A' + 10) * 16 } else if 'a' <= r5 && r5 <= 'f' { r += (r5 - 'a' + 10) * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r6 && r6 <= '9' { r += r6 - '0' } else if 'A' <= r6 && r6 <= 'F' { r += r6 - 'A' + 10 } else if 'a' <= r6 && r6 <= 'f' { r += r6 - 'a' + 10 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } case 'v': r = '\v' case 'x': r3, _, err := runeScanner.ReadRune() if nil != err { msg := "Problem after reading hexadecimal escape “\\x”." return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r3) r4, _, err := runeScanner.ReadRune() if nil != err { msg := fmt.Sprintf("Problem after reading hexadecimal escape “\\x%s”.", string(r3)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } code.buffer.WriteRune(r4) if !(('0' <= r3 && r3 <= '9') || ('A' <= r3 && r3 <= 'F') || ('a' <= r3 && r3 <= 'f')) { msg := fmt.Sprintf("Invalid hexadecimal escape sequence: “\\x%s%s”.", string(r3), string(r4)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } if !(('0' <= r4 && r4 <= '9') || ('A' <= r4 && r4 <= 'F') || ('a' <= r4 && r4 <= 'f')) { msg := fmt.Sprintf("Invalid hexadecimal escape sequence: “\\x%s%s”.", string(r3), string(r4)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } r = 0 if '0' <= r3 && r3 <= '9' { r += (r3 - '0') * 16 } else if 'A' <= r3 && r3 <= 'F' { r += (r3 - 'A' + 10) * 16 } else if 'a' <= r3 && r3 <= 'f' { r += (r3 - 'a' + 10) * 16 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } if '0' <= r4 && r4 <= '9' { r += r4 - '0' } else if 'A' <= r4 && r4 <= 'F' { r += r4 - 'A' + 10 } else if 'a' <= r4 && r4 <= 'f' { r += r4 - 'a' + 10 } else { return nil, nil, newSyntaxErrorComplainer(code.String(), "THIS SHOULD NEVER HAPPEN!") } case '\\': r = '\\' case '\'': r = '\'' case '"': r = '"' case '?': r = '?' case '‘': r = '‘' case '’': r = '’' case '“': r = '“' case '”': r = '”' case '‹': r = '‹' case '›': r = '›' case '«': r = '«' case '»': r = '»' default: msg := fmt.Sprintf("Invalid blackslash escape sequence: \\%s", string(r2)) return nil, nil, newSyntaxErrorComplainer(code.String(), msg) } } compiled.buffer.WriteRune(r) } return compiled, code, nil }
func readToken(r io.RuneScanner) (token, error) { // Tokenizer states const ( READY = iota READING STRLIT ESCAPE COMMENT ) // Single-rune tokens const TOKS = "()" const WS = " \t\r\n" const SPLIT = TOKS + WS + ";" const PROTECT = '\'' state := READY var tmp bytes.Buffer ch, _, err := r.ReadRune() if err != nil { return "", err } for err == nil { switch state { case READY: // c either begins or is a token if strings.ContainsRune(TOKS, ch) { return token(ch), nil } else if strings.ContainsRune(WS, ch) { // whitespace; ignore it } else if ch == ';' { // read to EOL state = COMMENT } else if ch == '"' { tmp.WriteRune(ch) state = STRLIT } else if ch == PROTECT { return token(ch), nil } else { tmp.WriteRune(ch) state = READING } case READING: if strings.ContainsRune(SPLIT, ch) { // the current token is done tok := token(tmp.String()) tmp.Reset() state = READY r.UnreadRune() return tok, nil } else { tmp.WriteRune(ch) } case STRLIT: if ch == '\\' { state = ESCAPE } else { tmp.WriteRune(ch) if ch == '"' { tok := token(tmp.String()) tmp.Reset() state = READY return tok, nil } } case ESCAPE: switch ch { case 'n': tmp.WriteRune('\n') case 't': tmp.WriteRune('\t') default: panic("Invalid escape character") } state = STRLIT case COMMENT: if ch == '\n' { state = READY } default: panic("Invalid state") } ch, _, err = r.ReadRune() } if err != io.EOF { return "", err } switch state { case READY: return "", err case COMMENT: return "", err } panic("Unexpected EOF") }
func ed(rs io.RuneScanner) (Edit, error) { a, err := parseCompoundAddr(rs) switch { case err != nil: return nil, err case a == nil: switch r, _, err := rs.ReadRune(); { case err == io.EOF: return Set(Dot, '.'), nil case err != nil: return nil, err case r == 'u': n, err := parseNumber(rs) if err != nil { return nil, err } return Undo(n), nil case r == 'r': n, err := parseNumber(rs) if err != nil { return nil, err } return Redo(n), nil default: if err := rs.UnreadRune(); err != nil { return nil, err } a = Dot } } switch r, _, err := rs.ReadRune(); { case err == io.EOF || err == nil && r == '\n': return Set(a, '.'), nil case err != nil: return nil, err case r == 'a' || r == 'c' || r == 'i': text, err := parseText(rs) if err != nil { return nil, err } switch r { case 'a': return Append(a, text), nil case 'c': return Change(a, text), nil default: // case 'i' return Insert(a, text), nil } case r == 'd': return Delete(a), nil case r == 'k': m, err := parseMarkRune(rs) if err != nil { return nil, err } return Set(a, m), nil case r == 'p': return Print(a), nil case r == '=': switch r, _, err := rs.ReadRune(); { case err == io.EOF: return WhereLine(a), nil case err != nil: return nil, err case r == '#': return Where(a), nil default: if err := rs.UnreadRune(); err != nil { return nil, err } return WhereLine(a), nil } case r == 't' || r == 'm': a1, err := parseAddrOrDot(rs) if err != nil { return nil, err } if r == 't' { return Copy(a, a1), nil } return Move(a, a1), nil case r == 's': n, err := parseNumber(rs) if err != nil { return nil, err } exp, err := parseRegexp2(rs) if err != nil { return nil, err } if len(exp) < 2 || len(exp) == 2 && exp[0] == exp[1] { // len==1 is just the open delim. // len==2 && exp[0]==exp[1] is just open and close delim. return nil, errors.New("missing pattern") } repl, err := parseDelimited(exp[0], rs) if err != nil { return nil, err } sub := Substitute{ A: a, RE: string(exp), With: string(repl), From: n, } switch r, _, err := rs.ReadRune(); { case err == io.EOF: return sub, nil case err != nil: return nil, err case r == 'g': sub.Global = true default: if err := rs.UnreadRune(); err != nil { return nil, err } } return sub, nil case r == '|' || r == '>' || r == '<': c, err := parseCmd(rs) if err != nil { return nil, err } switch r { case '|': return Pipe(a, c), nil case '>': return PipeTo(a, c), nil default: // case '<' return PipeFrom(a, c), nil } default: return nil, errors.New("unknown command: " + string(r)) } }