예제 #1
2
// New creates a RangeTable from the given runes, which may contain duplicates.
func New(r ...rune) *unicode.RangeTable {
	if len(r) == 0 {
		return &unicode.RangeTable{}
	}

	sort.Sort(byRune(r))

	// Remove duplicates.
	k := 1
	for i := 1; i < len(r); i++ {
		if r[k-1] != r[i] {
			r[k] = r[i]
			k++
		}
	}

	var rt unicode.RangeTable
	for _, r := range r[:k] {
		if r <= 0xFFFF {
			rt.R16 = append(rt.R16, unicode.Range16{Lo: uint16(r), Hi: uint16(r), Stride: 1})
		} else {
			rt.R32 = append(rt.R32, unicode.Range32{Lo: uint32(r), Hi: uint32(r), Stride: 1})
		}
	}

	// Optimize RangeTable.
	return Merge(&rt)
}
예제 #2
1
func addR16ToTable(r *unicode.RangeTable, r16 unicode.Range16) {
	if r.R16 == nil {
		r.R16 = make([]unicode.Range16, 0, 1)
	}
	r.R16 = append(r.R16, r16)
	if r16.Hi <= unicode.MaxLatin1 {
		r.LatinOffset++
	}
}
예제 #3
0
func Range(lo, hi rune) Matcher {
	if lo > hi {
		return Fail()
	}
	var t unicode.RangeTable
	if lo >= 0x10000 {
		t.R32 = append(t.R32, unicode.Range32{Lo: uint32(lo), Hi: uint32(hi), Stride: 1})
	} else if hi < 0x10000 {
		t.R16 = append(t.R16, unicode.Range16{Lo: uint16(lo), Hi: uint16(hi), Stride: 1})
		if hi < 0x100 {
			t.LatinOffset = 1
		}
	} else {
		t.R16 = append(t.R16, unicode.Range16{Lo: uint16(lo), Hi: 0xffff, Stride: 1})
		t.R32 = append(t.R32, unicode.Range32{Lo: 0x10000, Hi: uint32(hi), Stride: 1})
	}
	return charClassMatcher{false, t}
}
예제 #4
0
func CharClass(negated bool, table *unicode.RangeTable) Matcher {
	var t unicode.RangeTable
	t.R16 = make([]unicode.Range16, len(table.R16))
	copy(t.R16, table.R16)
	t.R32 = make([]unicode.Range32, len(table.R32))
	copy(t.R32, table.R32)
	t.LatinOffset = table.LatinOffset
	return charClassMatcher{negated, t}
}
예제 #5
0
func OneOf(chars ...rune) Matcher {
	if len(chars) == 0 {
		return Fail()
	}
	var t unicode.RangeTable
	sort.Sort(utf8betical(chars))
	for _, ch := range chars {
		if ch >= 0x10000 {
			t.R32 = append(t.R32, unicode.Range32{Lo: uint32(ch), Hi: uint32(ch), Stride: 1})
		} else {
			t.R16 = append(t.R16, unicode.Range16{Lo: uint16(ch), Hi: uint16(ch), Stride: 1})
			if ch < 0x100 {
				t.LatinOffset += 1
			}
		}
	}
	return charClassMatcher{false, t}
}
예제 #6
0
func appendRange16(t *unicode.RangeTable, lo, hi uint16) error {
	if t.R16 == nil || len(t.R16) == 0 {
		t.R16 = append(t.R16, unicode.Range16{lo, hi, 1})
		if hi <= unicode.MaxLatin1 {
			t.LatinOffset++
		}
		return nil
	}

	range_ := &t.R16[len(t.R16)-1]
	if lo <= range_.Hi {
		return fmt.Errorf("AppendRange: lo must be greater than Hi of the last range: lo=%d", lo)
	}

	if lo == hi {
		if range_.Hi+range_.Stride == lo {
			range_.Hi = lo
			if len(t.R16) >= 2 {
				prevR := &t.R16[len(t.R16)-2]
				if prevR.Stride > 1 && prevR.Hi+1 == range_.Lo {
					prevCount := (prevR.Hi-prevR.Lo)/prevR.Stride + 1
					count := (range_.Hi-range_.Lo)/range_.Stride + 1
					if prevCount <= count {
						range_.Lo--
						prevR.Hi -= prevR.Stride
						if prevR.Lo == prevR.Hi {
							prevR.Stride = 1
						}
					}
				}
			}
		} else if range_.Lo == range_.Hi {
			range_.Hi = lo
			range_.Stride = lo - range_.Lo
		} else {
			t.R16 = append(t.R16, unicode.Range16{lo, hi, 1})
			if hi <= unicode.MaxLatin1 {
				t.LatinOffset++
			}
		}
	} else {
		if range_.Stride == 1 {
			if lo-1 <= range_.Hi {
				range_.Hi = hi
			} else {
				if range_.Lo == range_.Hi {
					range_.Hi = hi
					range_.Stride = range_.Hi - range_.Lo
				} else {
					t.R16 = append(t.R16, unicode.Range16{lo, hi, 1})
					if hi <= unicode.MaxLatin1 {
						t.LatinOffset++
					}
				}
			}
		} else {
			if lo-1 <= range_.Hi {
				range_.Hi -= range_.Stride
				if range_.Lo == range_.Hi {
					range_.Stride = 1
				}
				t.R16 = append(t.R16, unicode.Range16{lo - 1, hi, 1})
				if hi <= unicode.MaxLatin1 {
					t.LatinOffset++
				}
			} else {
				t.R16 = append(t.R16, unicode.Range16{lo, hi, 1})
				if hi <= unicode.MaxLatin1 {
					t.LatinOffset++
				}
			}
		}
	}
	return nil
}