// StringToVersion function parses a string into a Version struct which can be compared // // The implementation is based on http://man.he.net/man5/deb-version // on https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version // // It uses the dpkg-1.17.25's algorithm (lib/parsehelp.c) func StringToVersion(str string) (Version, error) { var version Version // Trim leading and trailing space str = strings.TrimSpace(str) if len(str) <= 0 { return Version{}, errors.New("Version string is empty") } // Find Epoch sepEpoch := strings.Index(str, ":") if sepEpoch > -1 { intEpoch, err := strconv.Atoi(str[:sepEpoch]) if err == nil { version.Epoch = intEpoch } else { return Version{}, errors.New("Epoch in version is not a number") } if intEpoch < 0 { return Version{}, errors.New("Epoch in version is negative") } } else { version.Epoch = 0 } // Find UpstreamVersion / DebianRevision sepDebianRevision := strings.LastIndex(str, "-") if sepDebianRevision > -1 { version.UpstreamVersion = str[sepEpoch+1 : sepDebianRevision] version.DebianRevision = str[sepDebianRevision+1:] } else { version.UpstreamVersion = str[sepEpoch+1:] version.DebianRevision = "0" } // Verify format if len(version.UpstreamVersion) == 0 { return Version{}, errors.New("No UpstreamVersion in version") } if !unicode.IsDigit(rune(version.UpstreamVersion[0])) { return Version{}, errors.New("UpstreamVersion in version does not start with digit") } for i := 0; i < len(version.UpstreamVersion); i = i + 1 { r := rune(version.UpstreamVersion[i]) if !unicode.IsDigit(r) && !unicode.IsLetter(r) && !containsRune(upstreamVersionAllowedSymbols, r) { return Version{}, errors.New("invalid character in UpstreamVersion") } } for i := 0; i < len(version.DebianRevision); i = i + 1 { r := rune(version.DebianRevision[i]) if !unicode.IsDigit(r) && !unicode.IsLetter(r) && !containsRune(debianRevisionAllowedSymbols, r) { return Version{}, errors.New("invalid character in DebianRevision") } } return version, nil }
/* StringTrimNonAlnum remove non alpha-numeric character at the beginning and end for `text`. */ func StringTrimNonAlnum(text string) string { r := []rune(text) rlen := len(r) start := 0 for ; start < rlen; start++ { if unicode.IsLetter(r[start]) || unicode.IsDigit(r[start]) { break } } if start >= rlen { return "" } r = r[start:] rlen = len(r) end := rlen - 1 for ; end >= 0; end-- { if unicode.IsLetter(r[end]) || unicode.IsDigit(r[end]) { break } } if end < 0 { return "" } r = r[:end+1] return string(r) }
func delta(a, b string, elapsed time.Duration, w io.Writer) { var ai, bi int for { for ai < len(a) && !unicode.IsDigit(rune(a[ai])) { w.Write([]byte{a[ai]}) ai++ } for bi < len(b) && !unicode.IsDigit(rune(b[bi])) { bi++ } if ai == len(a) { break } numA, lenA := collectDigits(a[ai:]) ai += lenA numB, lenB := collectDigits(b[bi:]) bi += lenB // TODO: look at the next words, what's the unit? // TODO: colors // TODO: KB/MB fmt.Fprintf(w, "%.2f/s", float64(numB-numA)/(float64(elapsed)/float64(time.Second*1))) } fmt.Fprintln(w) }
// GetNextInt returns the next base-10 integer read from a netpbmReader, // skipping preceding whitespace and comments. func (nr *netpbmReader) GetNextInt() int { // Find the first digit. var c rune for nr.err == nil && !unicode.IsDigit(c) { for c = nr.GetNextByteAsRune(); unicode.IsSpace(c); c = nr.GetNextByteAsRune() { } if c == '#' { // Comment -- discard the rest of the line. for c = nr.GetNextByteAsRune(); c != '\n'; c = nr.GetNextByteAsRune() { } } } if nr.err != nil { return -1 } // Read while we have base-10 digits. Return the resulting int. value := int(c - '0') for c = nr.GetNextByteAsRune(); unicode.IsDigit(c); c = nr.GetNextByteAsRune() { value = value*10 + int(c-'0') } if nr.err != nil { return -1 } nr.err = nr.UnreadByte() if nr.err != nil { return -1 } return value }
// lexValueSequence scans a value sequence of a series description. func lexValueSequence(l *lexer) stateFn { switch r := l.next(); { case r == eof: return lexStatements case isSpace(r): lexSpace(l) case r == '+': l.emit(itemADD) case r == '-': l.emit(itemSUB) case r == 'x': l.emit(itemTimes) case r == '_': l.emit(itemBlank) case unicode.IsDigit(r) || (r == '.' && unicode.IsDigit(l.peek())): l.backup() lexNumber(l) case isAlpha(r): l.backup() // We might lex invalid items here but this will be caught by the parser. return lexKeywordOrIdentifier default: return l.errorf("unexpected character in series sequence: %q", r) } return lexValueSequence }
func ParseQuestion(s string) *Question { var isDigit bool positions := make([]int, 0) i, start := 0, -1 for _, c := range s { isDigit = unicode.IsDigit(c) if start == -1 { if isDigit { start = i } } else if !isDigit { // Include a number's decimals, commas, and trailing commas (for percentages) if c != '%' && !((c == '.' || c == ',') && i < len(s)-1 && unicode.IsDigit(rune(s[i+1]))) { positions = append(positions, start, i-1) start = -1 } } i++ } if len(positions) > 0 { return &Question{ FullText: s, Positions: positions, } } else { return nil } }
// extractLetterSequence extracts first word (sequence of letters ending with a non-letter) // starting with the specified index and wraps it to dateStringLayoutItem according to the type // of the word. func extractLetterSequence(originalStr string, index int) (it dateStringLayoutItem) { letters := "" bytesToParse := []byte(originalStr[index:]) runeCount := utf8.RuneCount(bytesToParse) var isWord bool var isDigit bool for i := 0; i < runeCount; i++ { rune, runeSize := utf8.DecodeRune(bytesToParse) bytesToParse = bytesToParse[runeSize:] if i == 0 { isWord = unicode.IsLetter(rune) isDigit = unicode.IsDigit(rune) } else { if (isWord && (!unicode.IsLetter(rune) && !unicode.IsDigit(rune))) || (isDigit && !unicode.IsDigit(rune)) || (!isWord && unicode.IsLetter(rune)) || (!isDigit && unicode.IsDigit(rune)) { break } } letters += string(rune) } it.item = letters it.isWord = isWord it.isDigit = isDigit return }
// FmtFieldName formats a string as a struct key // // Example: // FmtFieldName("foo_id") // Output: FooID func FmtFieldName(s string) string { runes := []rune(s) for len(runes) > 0 && !unicode.IsLetter(runes[0]) && !unicode.IsDigit(runes[0]) { runes = runes[1:] } if len(runes) == 0 { return "_" } s = stringifyFirstChar(string(runes)) name := lintFieldName(s) runes = []rune(name) for i, c := range runes { ok := unicode.IsLetter(c) || unicode.IsDigit(c) if i == 0 { ok = unicode.IsLetter(c) } if !ok { runes[i] = '_' } } s = string(runes) s = strings.Trim(s, "_") if len(s) == 0 { return "_" } return s }
func scanFormat(l *State, fs string) string { i := 0 skipDigit := func() { if unicode.IsDigit(rune(fs[i])) { i++ } } flags := "-+ #0" for i < len(fs) && strings.ContainsRune(flags, rune(fs[i])) { i++ } if i >= len(flags) { Errorf(l, "invalid format (repeated flags)") } skipDigit() skipDigit() if fs[i] == '.' { i++ skipDigit() skipDigit() } if unicode.IsDigit(rune(fs[i])) { Errorf(l, "invalid format (width or precision too long)") } i++ return "%" + fs[:i] }
func lexIdSelector(l *Lexer) stateFn { var foundInterpolation = false var r = l.next() r = l.next() if !unicode.IsLetter(r) && r != '#' && l.peek() != '{' { l.error("An identifier should start with at least a letter, Got '%s'", r) } for { if IsInterpolationStartToken(r, l.peek()) { l.backup() lexInterpolation(l, false) foundInterpolation = true } else if !unicode.IsLetter(r) && !unicode.IsDigit(r) { break } r = l.next() } l.backup() r = l.next() for unicode.IsLetter(r) || unicode.IsDigit(r) { r = l.next() } l.backup() if foundInterpolation { l.emit(ast.T_INTERPOLATION_SELECTOR) } else { l.emit(ast.T_ID_SELECTOR) } return lexSelectors }
func lexNumberOrDurationOrDot(l *lexer) stateFn { foundDecimal := false first := true for { switch r := l.next(); { case r == '.': if first && !unicode.IsDigit(l.peek()) { l.emit(TokenDot) return lexToken } if foundDecimal { return l.errorf("multiple decimals in number") } foundDecimal = true case unicode.IsDigit(r): //absorb case !foundDecimal && isDurUnit(r): if r == 'm' && l.peek() == 's' { l.next() } l.emit(TokenDuration) return lexToken default: l.backup() l.emit(TokenNumber) return lexToken } first = false } }
func (p *PrimaryLexer) scanNumeral() { buf := new(bytes.Buffer) first := p.Consume() buf.WriteRune(first) if first == '0' && p.Peek() == 'x' { // Hexadecimal buf.WriteRune(p.Consume()) if !isHexadecimal(p.Peek()) { p.Emit(TokenError, "Expected digits after '0x' while lexing hexadecimal numeral") return } for isHexadecimal(p.Peek()) { buf.WriteRune(p.Consume()) } } else { // Decimal for unicode.IsDigit(p.Peek()) { buf.WriteRune(p.Consume()) } // Decimal digits if p.Peek() == '.' { dot := p.Consume() // Special case: 'digits' '..' 'expr' if !unicode.IsDigit(p.Peek()) { p.Emit(TokenNumeral, buf.String()) p.Emit(TokenSymbol, ".") return } buf.WriteRune(dot) for unicode.IsDigit(p.Peek()) { buf.WriteRune(p.Consume()) } } // Exponent if p.Peek() == 'e' { buf.WriteRune(p.Consume()) if !unicode.IsDigit(p.Peek()) { p.Emit(TokenError, "Expected digits after '"+buf.String()+"' while lexing exponent of numeral") return } for unicode.IsDigit(p.Peek()) { buf.WriteRune(p.Consume()) } } } p.Emit(TokenNumeral, buf.String()) }
// scanNumber consumes a numeric lexeme and returns its token and value. The // numeric value may be an integer or real number. func (s *Scanner) scanNumber() (token.Token, string) { var ch rune var buf bytes.Buffer buf.WriteRune(s.read()) for { ch = s.read() if !unicode.IsDigit(ch) { break } buf.WriteRune(ch) } if ch == '.' { buf.WriteRune(ch) for { ch = s.read() if !unicode.IsDigit(ch) { break } buf.WriteRune(ch) } } s.unread() return token.NUMBER, buf.String() }
// statefull tokenizer for linux printk() message buffer // // BUG(nath): may need some generic API func get_klog_tokenizer() func(rune) bool { started := false state := "priority" return func(c rune) bool { switch state { case "dispatch": switch { case c == '<': state = "priority" started = true return true case c == '[': state = "date" started = true return true case started: state = "message" return unicode.IsSpace(c) default: started = true return true } case "priority": switch { case c == '<': return true case c == '>': state = "dispatch" return true default: return !unicode.IsDigit(c) } case "date": switch { case c == '[' || c == '.': return true case c == ']': state = "dispatch" return true default: return !unicode.IsDigit(c) } default: return false } } }
func (c *Cursor) AtEow() bool { r, _ := c.RuneAfter() rb, _ := c.RuneBefore() if !(unicode.IsLetter(r) || unicode.IsDigit(r)) && (unicode.IsLetter(rb) || unicode.IsDigit(rb)) { return true } return false }
func (l keyList) Less(i, j int) bool { a := l[i] b := l[j] ak := a.Kind() bk := b.Kind() for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { a = a.Elem() ak = a.Kind() } for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { b = b.Elem() bk = b.Kind() } af, aok := keyFloat(a) bf, bok := keyFloat(b) if aok && bok { if af != bf { return af < bf } if ak != bk { return ak < bk } return numLess(a, b) } if ak != reflect.String || bk != reflect.String { return ak < bk } ar, br := []rune(a.String()), []rune(b.String()) for i := 0; i < len(ar) && i < len(br); i++ { if ar[i] == br[i] { continue } al := unicode.IsLetter(ar[i]) bl := unicode.IsLetter(br[i]) if al && bl { return ar[i] < br[i] } if al || bl { return bl } var ai, bi int var an, bn int64 for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { an = an*10 + int64(ar[ai]-'0') } for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { bn = bn*10 + int64(br[bi]-'0') } if an != bn { return an < bn } if ai != bi { return ai < bi } return ar[i] < br[i] } return len(ar) < len(br) }
func lexStart(l *lexer) stateFn { switch r := l.next(); { case isWhitespace(r): return lexWhitespace case r == '(': l.emit(LPAREN) return lexStart case r == ')': l.emit(RPAREN) return lexStart case r == '\'': l.emit(QUOTE) return lexStart case r == '`': l.emit(BACKTICK) return lexStart case r == ',': if l.peek() == '@' { l.next() l.emit(COMMAAT) } else { l.emit(COMMA) } return lexStart case r == '.' && !unicode.IsDigit(l.peek()): l.emit(DOT) return lexStart case (r == '+' || r == '-') && !unicode.IsDigit(l.peek()): l.emit(IDENT) return lexStart case r == '.' || r == '+' || r == '-' || ('0' <= r && r <= '9'): l.backup() return lexNumber case r == '"': l.ignore() return lexString case r == '#': switch r = l.next(); { case r == 't' || r == 'f': l.backup() return lexBoolean case r == '\\': return lexCharacter case r == '(': l.emit(LVEC) return lexStart default: return l.errorf("bad # sequence") } case r == eof || r == '\n': return nil default: l.backup() return lexIdentifier } return lexStart }
func readSymbolOrNumber(prt *port, head rune) (yObj, error) { var ( c rune e error ) if head != -1 { c, e = head, nil } else { c, _, e = prt.rdr.ReadRune() } if e != nil { return nil, mkYerror(errRead, errIntern) } switch c { case '.': next, _, e := prt.rdr.ReadRune() if e != nil { return nil, mkYerror(errRead, errIntern) } if next == '.' { e = prt.rdr.UnreadRune() if e != nil { return nil, mkYerror(errRead, errIntern) } return readSymbol(prt, '.') } if unicode.IsDigit(next) { e = prt.rdr.UnreadRune() if e != nil { return nil, mkYerror(errRead, errIntern) } return readNumber(prt, c) } return nil, mkYerror(errRead, errSyntax, "malformed dot syntax") case '+', '-': next, _, e := prt.rdr.ReadRune() if e != nil { return nil, mkYerror(errRead, errIntern) } if unicode.IsDigit(next) || (next >= 'a' && next <= 'f') || next == 'i' || next == '.' { e = prt.rdr.UnreadRune() if e != nil { return nil, mkYerror(errRead, errIntern) } return readNumber(prt, c) } e = prt.rdr.UnreadRune() if e != nil { return nil, mkYerror(errRead, errIntern) } return readSymbol(prt, c) default: return nil, mkYerror(errRead, errSyntax, "unrecognized syntax") } }
func (l *lexer) ident(c rune) { cp := &lexbuf cp.Reset() // accelerate common case (7bit ASCII) for isLetter(c) || isDigit(c) { cp.WriteByte(byte(c)) c = l.getr() } // general case for { if c >= utf8.RuneSelf { if unicode.IsLetter(c) || c == '_' || unicode.IsDigit(c) { if cp.Len() == 0 && unicode.IsDigit(c) { yyerror("identifier cannot begin with digit %#U", c) } } else { yyerror("invalid identifier character %#U", c) } cp.WriteRune(c) } else if isLetter(c) || isDigit(c) { cp.WriteByte(byte(c)) } else { break } c = l.getr() } cp = nil l.ungetr() name := lexbuf.Bytes() if len(name) >= 2 { if tok, ok := keywords[string(name)]; ok { if Debug['x'] != 0 { fmt.Printf("lex: %s\n", lexname(tok)) } switch tok { case LBREAK, LCONTINUE, LFALL, LRETURN: l.nlsemi = true } l.tok = tok return } } s := lookupBytes(name) if Debug['x'] != 0 { fmt.Printf("lex: ident %v\n", s) } l.sym_ = s l.nlsemi = true l.tok = LNAME }
// Consume a single rune; assumes this is being invoked as the last possible // option and will panic if an invalid escape sequence is found. Will return the // found rune (as an integer) and with cursor past the entire representation. func (p *parser) single_rune() rune { if r := p.src.curr(); r != '\\' { // This is just a regular character; return it immediately. p.src.nextCh() return r } if p.src.peek() == 'x' { // Match hex character code. var hex string p.src.nextCh() if p.src.nextCh() == '{' { hex = p.src.literal("{", "}") } else { hex = fmt.Sprintf("%c%c", p.src.curr(), p.src.nextCh()) p.src.nextCh() // Step over the end of the hex code. } // Parse and return the corresponding rune. raw, err := strconv.ParseUint(hex, 16, 32) if err != nil { panic(fmt.Sprintf("couldn't parse hex: %s", hex)) } return rune(raw) } else if r := ESCAPES[p.src.peek()]; r != 0 { // Literally match '\n', '\r', etc. p.src.nextCh() p.src.nextCh() return r } else if unicode.Is(posix_groups["punct"], p.src.peek()) { // Allow punctuation to be blindly escaped. r := p.src.nextCh() p.src.nextCh() return r } else if unicode.IsDigit(p.src.peek()) { // Match octal character code (begins with digit, up to three digits). oct := "" p.src.nextCh() for i := 0; i < 3; i++ { oct += fmt.Sprintf("%c", p.src.curr()) if !unicode.IsDigit(p.src.nextCh()) { break } } // Parse and return the corresponding rune. raw, err := strconv.ParseUint(oct, 8, 32) if err != nil { panic(fmt.Sprintf("couldn't parse oct: %s", oct)) } return rune(raw) } // This is an escape sequence which does not identify a single rune. panic(fmt.Sprintf("not a valid escape sequence: \\%c", p.src.peek())) }
func lexWhitespace(l *Lexer) StateFn { var r rune for r = l.next(); isSpace(r); r = l.next() { } l.backward() l.ignore() switch r = l.next(); { case r == '(': return lexLeftParen case r == ')': return lexRightParen case r == '[': return lexLeftVect case r == ']': return lexRightVect case r == '"': return lexString case r == '\'': return lexQuote case r == '`': return lexQuasiQuote case r == ',': if l.next() == '@' { return lexUnQuoteSplicing } else { l.backward() return lexUnQuote } case r == ';': return lexComment case r == '#': return lexSharp case r == '-' || r == '+' || unicode.IsDigit(r): // number or ident next := l.peek() if next == EOF { panic("expected number or procedure") } if !unicode.IsDigit(r) && isSpace(next) { return lexIdentifier } if scanNumber(l) { return lexNumber } case isAlphaNumeric(r): l.backward() return lexIdentifier case r == EOF: return lexEOF } return nil }
// lexNext lexes the item immediately following an identifier func lexNext(l *lexer) stateFn { r := l.next() switch { case r == eof: return l.errorf("statement unterminated by '.'") case r == '.': if l.peek() == '(' { l.emit(itemAtom) } else { l.emit(itemDot) return lexSpace } case r == '|': l.emit(itemPipe) case r == '!': l.emit(itemCut) case r == ',': l.emit(itemComma) case r == '(': l.emit(itemLeftParen) l.parenDepth++ case r == ')': l.emit(itemRightParen) l.parenDepth-- if l.parenDepth < 0 { return l.errorf("unexpected right paren %#U", r) } case r == '[': l.emit(itemLeftBrace) l.braceDepth++ case r == ']': l.emit(itemRightParen) l.parenDepth-- if l.parenDepth < 0 { return l.errorf("unexpected right paren %#U", r) } case unicode.IsDigit(r): return lexNumber case unicode.IsUpper(r) || r == '_': return lexVariable case unicode.IsLower(r): return lexAtom case r == '\'' || r == '"': l.backup() return lexQuoted case unicode.IsDigit(r): l.backup() return lexNumber default: l.errorf("unexpected character %#U", r) } return lexNext }
func GetLastWord(linesrc string, off int) ([]string, []string) { wordsLeft := strings.FieldsFunc(linesrc[:off], func(r rune) bool { return !(unicode.IsLetter(r) || unicode.IsDigit(r)) }) wordsRight := strings.FieldsFunc(linesrc[off:], func(r rune) bool { return !(unicode.IsLetter(r) || unicode.IsDigit(r)) }) return wordsLeft, wordsRight }
func lexNumber(l *Lexer) stateFn { for r := l.peek(); unicode.IsDigit(r); { l.next() r = l.peek() } l.accept(".") for r := l.peek(); unicode.IsDigit(r); { l.next() r = l.peek() } l.emit(token.NUMBER) return lexStatement }
// Specialized function for TeX-style hyphenation patterns. Accepts strings of the form '.hy2p'. // The value it stores is of type vector.IntVector func (p *Trie) AddPatternString(s string) { v := new(vector.IntVector) // precompute the Unicode rune for the character '0' rune0, _ := utf8.DecodeRune([]byte{'0'}) strLen := len(s) // Using the range keyword will give us each Unicode rune. for pos, rune := range s { if unicode.IsDigit(rune) { if pos == 0 { // This is a prefix number v.Push(rune - rune0) } // this is a number referring to the previous character, and has // already been handled continue } if pos < strLen-1 { // look ahead to see if it's followed by a number next := int(s[pos+1]) if unicode.IsDigit(next) { // next char is the hyphenation value for this char v.Push(next - rune0) } else { // hyphenation for this char is an implied zero v.Push(0) } } else { // last character gets an implied zero v.Push(0) } } pure := strings.Map(func(rune int) int { if unicode.IsDigit(rune) { return -1 } return rune }, s) leaf := p.addRunes(strings.NewReader(pure)) if leaf == nil { return } leaf.value = v }
func _dl_cache_libcmp(p1, p2 string) int { // log.Printf("Compare %q and %q", p1, p2) l := len(p1) if len(p2) < l { l = len(p2) } parseLeadingNum := func(s string) int { nonDigit := func(r rune) bool { return !unicode.IsDigit(r) } firstNonDigit := strings.IndexFunc(s, nonDigit) if firstNonDigit == -1 { // No numbers before end of string firstNonDigit = len(s) } n, err := strconv.ParseInt(s[:firstNonDigit], 10, 32) if err != nil { panic(err) } return int(n) } for i := 0; i < l; i++ { p1c, p2c := p1[i], p2[i] switch { case unicode.IsDigit(rune(p1c)) && unicode.IsDigit(rune(p2c)): // Must do a numerical compare. n1 := parseLeadingNum(p1[i:]) n2 := parseLeadingNum(p2[i:]) switch { case n1 < n2: return -1 case n1 > n2: return 1 } case unicode.IsDigit(rune(p1c)): return 1 case unicode.IsDigit(rune(p2c)): return -1 case p1c < p2c: return -1 case p1c > p2c: return 1 } } switch { case len(p1) < len(p2): return -1 case len(p1) > len(p2): return 1 } return 0 }
// These two steps (comparing and removing initial non-digit strings and initial digit strings) are // repeated until a difference is found or both strings are exhausted." func compareVersionPart(part1, part2 string) int { i1, i2 := 0, 0 l1, l2 := len(part1), len(part2) for { j1, j2 := i1, i2 for j1 < l1 && !unicode.IsDigit(rune(part1[j1])) { j1++ } for j2 < l2 && !unicode.IsDigit(rune(part2[j2])) { j2++ } s1, s2 := part1[i1:j1], part2[i2:j2] r := compareLexicographic(s1, s2) if r != 0 { return r } i1, i2 = j1, j2 for j1 < l1 && unicode.IsDigit(rune(part1[j1])) { j1++ } for j2 < l2 && unicode.IsDigit(rune(part2[j2])) { j2++ } s1, s2 = part1[i1:j1], part2[i2:j2] n1, _ := strconv.Atoi(s1) n2, _ := strconv.Atoi(s2) if n1 < n2 { return -1 } if n1 > n2 { return 1 } i1, i2 = j1, j2 if i1 == l1 && i2 == l2 { break } } return 0 }
func (self *tokenizer) Next() { self.token.Value = "" // Skip whitespace for unicode.IsSpace(self.char) { self.nextChar() } if self.char == '(' { self.token.Type = TOK_OPEN self.nextChar() } else if self.char == ')' { self.token.Type = TOK_CLOSE self.nextChar() } else if self.char == '.' { self.token.Type = TOK_DOT self.nextChar() } else if unicode.IsDigit(self.char) { self.token.Type = TOK_FIXNUM for { self.token.Value += string(self.char) self.nextChar() if !unicode.IsDigit(self.char) { break } } } else if isValidSymbolChar(self.char) { self.token.Type = TOK_SYMBOL for { self.token.Value += string(self.char) self.nextChar() if !isValidSymbolChar(self.char) { break } } } else { // End of input self.token.Type = TOK_EOF } }
func lexNumber(l *GutsLex) stateFn { var c rune for c = l.next(); true; c = l.next() { if unicode.IsDigit(c) { continue } else if c == '.' && unicode.IsDigit(l.peek()) { return lexFloating } else { break } } l.backup() l.emit(T_NUMBER) return lexStart }
func envValid(env string) bool { items := strings.Split(env, "=") if len(items) < 2 { return false } for i, ch := range strings.TrimSpace(items[0]) { if !unicode.IsDigit(ch) && !unicode.IsLetter(ch) && ch != '_' { return false } if i == 0 && unicode.IsDigit(ch) { logrus.Warnf("Env %v: variable name beginning with digit is not recommended.", env) } } return true }