Source File
unicode29_rules.go
Belonging Package
github.com/go-text/typesetting/segmenter
// SPDX-License-Identifier: Unlicense OR BSD-3-Clausepackage segmenterimport (ucd)// -----------------------------------------------------------------------// ------------------------- Grapheme boundaries -------------------------// -----------------------------------------------------------------------// Apply the Grapheme_Cluster_Boundary_Rules and returns a true if we are// at a grapheme break.// See https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rulesfunc ( *cursor) () bool {:= .updateIndicConjunctBreakSequence() // apply rule GB9c:= .updatePictoSequence() // apply rule GB11:= .updateGraphemeRIOdd() // apply rule GB12 and GB13, := .prevGrapheme, .graphemeif .r == '\n' && .prev == '\r' {return false // Rule GB3} else if &(ucd.GB_Control|ucd.GB_CR|ucd.GB_LF) != 0 ||&(ucd.GB_Control|ucd.GB_CR|ucd.GB_LF) != 0 {return true // Rules GB4 && GB5} else if == ucd.GB_L && &(ucd.GB_L|ucd.GB_V|ucd.GB_LV|ucd.GB_LVT) != 0 { // rule GB6return false} else if &(ucd.GB_LV|ucd.GB_V) != 0 && &(ucd.GB_V|ucd.GB_T) != 0 {return false // rule GB7} else if &(ucd.GB_LVT|ucd.GB_T) != 0 && == ucd.GB_T {return false // rule GB8} else if &(ucd.GB_Extend|ucd.GB_ZWJ) != 0 {return false // Rule GB9} else if == ucd.GB_SpacingMark {return false // Rule GB9a} else if == ucd.GB_Prepend {return false // Rule GB9b} else if {return false // Rule GB9c} else if { // Rule GB11return false} else if {return false // Rule GB12 && GB13}return true // Rule GB999}// update `isPrevGraphemeRIOdd` used for the rules GB12 and GB13// and returns `true` if one of them triggeredfunc ( *cursor) () ( bool) {if .grapheme == ucd.GB_Regional_Indicator {= .isPrevGraphemeRIOdd.isPrevGraphemeRIOdd = !.isPrevGraphemeRIOdd // switch the parity} else {.isPrevGraphemeRIOdd = false}return}// see rule GB11type pictoSequenceState uint8const (noPictoSequence pictoSequenceState = iota // we are not in a sequenceinPictoExtend // we are in (ExtendedPic)(Extend*) patternseenPictoZWJ // we have seen (ExtendedPic)(Extend*)(ZWJ))// update the `pictoSequence` state used for rule GB11 pattern :// (ExtendedPic)(Extend*)(ZWJ)(ExtendedPic)// and returns true if we matched onefunc ( *cursor) () bool {switch .pictoSequence {case noPictoSequence:// we are not in a sequence yet, start it if we have an ExtendedPicif .isExtentedPic {.pictoSequence = inPictoExtend}return falsecase inPictoExtend:if .grapheme == ucd.GB_Extend {// continue the sequence with an Extend rune} else if .grapheme == ucd.GB_ZWJ {// close the variable part of the sequence with (ZWJ).pictoSequence = seenPictoZWJ} else {// stop the sequence.pictoSequence = noPictoSequence}return falsecase seenPictoZWJ:// trigger GB11 if we have an ExtendedPic,// and reset the sequenceif .isExtentedPic {.pictoSequence = inPictoExtendreturn true}.pictoSequence = noPictoSequencereturn falsedefault:panic("exhaustive switch")}}// see rule GB9ctype indicCBSequenceState uint8const (noIndicCBSequence indicCBSequenceState = iota // we are not in a sequenceinIndicCBSequence // we are in (Consonant) (Extend Linker)* patternseenIndicCBSequence // we have seen (Consonant) (Extend Linker)* (Linker) (Extend Linker)*)// update the `indicConjunctBreakSequence` state used for rule CB9c pattern :// (Consonant) (Extend Linker)* (Linker) (Extend Linker)* (Consonant)// and returns true if we matched onefunc ( *cursor) () bool {:= .indicConjunctBreakswitch .indicConjunctBreakSequence {case noIndicCBSequence:// we are not in a sequence yet, start it if we have a Consonantif == ucd.ICBConsonant {.indicConjunctBreakSequence = inIndicCBSequence}return falsecase inIndicCBSequence:if == ucd.ICBExtend {// continue the sequence} else if == ucd.ICBLinker {// we now have at least on Linker.indicConjunctBreakSequence = seenIndicCBSequence} else if == ucd.ICBConsonant {// reset the sequence} else {// stop the sequence.indicConjunctBreakSequence = noIndicCBSequence}return falsecase seenIndicCBSequence:if &(ucd.ICBExtend|ucd.ICBLinker) != 0 {// continue the sequencereturn false} else if == ucd.ICBConsonant {// start a new sequence.indicConjunctBreakSequence = inIndicCBSequencereturn true} else {// stop the sequence.indicConjunctBreakSequence = noIndicCBSequencereturn false}default:panic("exhaustive switch")}}// -----------------------------------------------------------------------// ------------------------- Word boundaries -----------------------------// -----------------------------------------------------------------------// update `isPrevWordRIOdd` used for the rules WB15 and WB16// and returns `true` if one of them triggeredfunc ( *cursor) () ( bool) {if .word == ucd.WB_ExtendFormat {return false // skip}if .word == ucd.WB_Regional_Indicator {= .isPrevWordRIOdd.isPrevWordRIOdd = !.isPrevWordRIOdd // switch the parity} else {.isPrevWordRIOdd = false}return}// Apply the Word_Boundary_Rules and returns true if we are at a// word boundary.// removePrevNoExtend is true if the index [prevWordNoExtend]// should be marked as NOT being a word boundary// See https://unicode.org/reports/tr29/#Word_Boundary_Rulesfunc ( *cursor) ( int) (, bool) {:= .updateWordRIOdd(), , := .prevPrevWord, .prevWord, .word// we apply Rules WB1 and WB2 at the end of the main loop:= .prevWordNoExtend == -1if .prev == '\u000D' && .r == '\u000A' { // Rule WB3= false} else if == ucd.WB_NewlineCRLF && {// The extra check for prevWordNoExtend is to correctly handle sequences like// Newline ÷ Extend × Extend// since we have not skipped ExtendFormat yet.= true // Rule WB3a} else if == ucd.WB_NewlineCRLF {= true // Rule WB3b} else if .prev == 0x200D && .isExtentedPic {= false // Rule WB3c} else if == ucd.WB_WSegSpace &&== ucd.WB_WSegSpace && {= false // Rule WB3d} else if == ucd.WB_ExtendFormat {= false // Rules WB4} else if &(ucd.WB_ALetter|ucd.WB_Hebrew_Letter|ucd.WB_Numeric) != 0 &&&(ucd.WB_ALetter|ucd.WB_Hebrew_Letter|ucd.WB_Numeric) != 0 {= false // Rules WB5, WB8, WB9, WB10} else if == ucd.WB_Katakana && == ucd.WB_Katakana {= false // Rule WB13} else if &(ucd.WB_ALetter|ucd.WB_Hebrew_Letter|ucd.WB_Numeric|ucd.WB_Katakana|ucd.WB_ExtendNumLet) != 0 &&== ucd.WB_ExtendNumLet {= false // Rule WB13a} else if == ucd.WB_ExtendNumLet &&&(ucd.WB_ALetter|ucd.WB_Hebrew_Letter|ucd.WB_Numeric|ucd.WB_Katakana) != 0 {= false // Rule WB13b} else if &(ucd.WB_ALetter|ucd.WB_Hebrew_Letter) != 0 &&&(ucd.WB_MidLetter|ucd.WB_MidNumLet|ucd.WB_Single_Quote) != 0 &&&(ucd.WB_ALetter|ucd.WB_Hebrew_Letter) != 0 {= true // Rule WB6= false // Rule WB7} else if == ucd.WB_Hebrew_Letter && == ucd.WB_Single_Quote {= false // Rule WB7a} else if == ucd.WB_Hebrew_Letter && .prev == 0x0022 &&== ucd.WB_Hebrew_Letter {= true // Rule WB7b= false // Rule WB7c} else if ( == ucd.WB_Numeric && == ucd.WB_Numeric) &&&(ucd.WB_MidNum|ucd.WB_MidNumLet|ucd.WB_Single_Quote) != 0 {= false // Rule WB11= true // Rule WB12} else if {= false // Rule WB15 and WB16} else {= true // Rule WB999}return ,}
![]() |
The pages are generated with Golds v0.8.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |