• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2002-2015  International Business Machines Corporation and
2# others. All Rights Reserved.
3#
4#  file:  line_loose_cj.txt
5#
6#         Line Breaking Rules
7#         Implement default line breaking as defined by
8#         Unicode Standard Annex #14 Revision 29 for Unicode 6.2
9#         http://www.unicode.org/reports/tr14/
10#         tailored as noted in 2nd paragraph below..
11#
12#         TODO:  Rule LB 8 remains as it was in Unicode 5.2
13#         This is only because of a limitation of ICU break engine implementation,
14#         not because the older behavior is desirable.
15#
16#         This tailors the line break behavior to correspond to CSS
17#         line-break=loose (BCP47 -u-lb-loose) as defined for Chinese & Japanese.
18#         It sets characters of class CJ to behave like ID.
19#         In addition, it allows breaks:
20#         * before hyphens 2010 & 2013 (both BA) and 301C, 30A0 (both NS)
21#         * before iteration marks 3005, 303B, 309D, 309E, 30FD, 30FE (all NS)
22#         * between characters of LineBreak class IN such as 2026
23#         * before some centered punct 203C, 2047, 2048, 2049, 30FB, FF1A, FF1B,
24#           FF65 (all NS) and FF01, FF1F (both EX).
25#         * before suffix characters with LineBreak class PO and EastAsianWidth A,F,W;
26#           this includes: 00B0 2030 2032 2033 2035 2103 2109 FE6A FF05 FFE0
27#         * after prefix characters with LineBreak class PR and EastAsianWidth A,F,W;
28#           this includes: 00A4 00B1 20AC 2116 FE69 FF04 FFE1 FFE5 FFE6
29
30
31#
32#  Character Classes defined by TR 14.
33#
34
35!!chain;
36!!LBCMNoChain;
37
38
39!!lookAheadHardBreak;
40#
41#  !!lookAheadHardBreak    Described here because it is (as yet) undocumented elsewhere
42#                          and only used for the line break rules.
43#
44#           It is used in the implementation of rule LB 10
45#           which says to treat any combining mark that is not attached to a base
46#           character as if it were of class AL  (alphabetic).
47#
48#           The problem occurs in the reverse rules.
49#
50#           Consider a sequence like, with correct breaks as shown
51#               LF  ID  CM  AL  AL
52#                  ^       ^       ^
53#           Then consider the sequence without the initial ID (ideographic)
54#                 LF  CM  AL  AL
55#                    ^           ^
56#           Our CM, which in the first example was attached to the ideograph,
57#           is now unattached, becomes an alpha, and joins in with the other
58#           alphas.
59#
60#           When iterating forwards, these sequences do not present any problems
61#           When iterating backwards, we need to look ahead when encountering
62#           a CM to see whether it attaches to something further on or not.
63#           (Look-ahead in a reverse rule is looking towards the start)
64#
65#           If the CM is unattached, we need to force a break.
66#
67#           !!lookAheadHardBreak forces the run time state machine to
68#           stop immediately when a look ahead rule ( '/' operator) matches,
69#           and set the match position to that of the look-ahead operator,
70#           no matter what other rules may be in play at the time.
71#
72#           See rule LB 19 for an example.
73#
74
75$AI = [:LineBreak =  Ambiguous:];
76$AL = [:LineBreak =  Alphabetic:];
77$BAX = [\u2010 \u2013];
78$BA = [[:LineBreak =  Break_After:] - $BAX];
79$BB = [:LineBreak =  Break_Before:];
80$BK = [:LineBreak =  Mandatory_Break:];
81$B2 = [:LineBreak =  Break_Both:];
82$CB = [:LineBreak =  Contingent_Break:];
83$CJ = [:LineBreak =  Conditional_Japanese_Starter:];
84$CL = [:LineBreak =  Close_Punctuation:];
85$CM = [:LineBreak =  Combining_Mark:];
86$CP = [:LineBreak =  Close_Parenthesis:];
87$CR = [:LineBreak =  Carriage_Return:];
88$EXX = [\uFF01 \uFF1F];
89$EX = [[:LineBreak =  Exclamation:] - $EXX];
90$GL = [:LineBreak =  Glue:];
91$HL = [:LineBreak =  Hebrew_Letter:];
92$HY = [:LineBreak =  Hyphen:];
93$H2 = [:LineBreak =  H2:];
94$H3 = [:LineBreak =  H3:];
95$ID = [[:LineBreak =  Ideographic:] $CJ];
96$IN = [:LineBreak =  Inseperable:];
97$IS = [:LineBreak =  Infix_Numeric:];
98$JL = [:LineBreak =  JL:];
99$JV = [:LineBreak =  JV:];
100$JT = [:LineBreak =  JT:];
101$LF = [:LineBreak =  Line_Feed:];
102$NL = [:LineBreak =  Next_Line:];
103$NSX = [\u301C \u30A0 \u3005 \u303B \u309D \u309E \u30FD \u30FE \u203C \u2047 \u2048 \u2049 \u30FB \uFF1A \uFF1B \uFF65];
104$NS = [[:LineBreak =  Nonstarter:] - $NSX];
105$NU = [:LineBreak =  Numeric:];
106$OP = [:LineBreak =  Open_Punctuation:];
107$POX = [\u00B0 \u2030 \u2032 \u2033 \u2035 \u2103 \u2109 \uFE6A \uFF05 \uFFE0];
108$PO = [[:LineBreak =  Postfix_Numeric:] - $POX];
109$PRX = [\u00A4 \u00B1 \u20AC \u2116 \uFE69 \uFF04 \uFFE1 \uFFE5 \uFFE6];
110$PR = [[:LineBreak =  Prefix_Numeric:] - $PRX];
111$QU = [:LineBreak =  Quotation:];
112$RI = [:LineBreak =  Regional_Indicator:];
113$SA = [:LineBreak =  Complex_Context:];
114$SG = [:LineBreak =  Surrogate:];
115$SP = [:LineBreak =  Space:];
116$SY = [:LineBreak =  Break_Symbols:];
117$WJ = [:LineBreak =  Word_Joiner:];
118$XX = [:LineBreak =  Unknown:];
119$ZW = [:LineBreak =  ZWSpace:];
120
121#   Dictionary character set, for triggering language-based break engines. Currently
122#   limited to LineBreak=Complex_Context. Note that this set only works in Unicode
123#   5.0 or later as the definition of Complex_Context was corrected to include all
124#   characters requiring dictionary break.
125
126$dictionary = [:LineBreak = Complex_Context:];
127
128#
129#  Rule LB1.  By default, treat AI  (characters with ambiguous east Asian width),
130#                               SA  (South East Asian: Thai, Lao, Khmer)
131#                               SG  (Unpaired Surrogates)
132#                               XX  (Unknown, unassigned)
133#                         as $AL  (Alphabetic)
134#
135$ALPlus = [$AL $AI $SA $SG $XX];
136
137#
138#  Combining Marks.   X $CM*  behaves as if it were X.  Rule LB6.
139#
140$ALcm = $ALPlus $CM*;
141$BAcm = $BA $CM*;
142$BAXcm = $BAX $CM*;
143$BBcm = $BB $CM*;
144$B2cm = $B2 $CM*;
145$CLcm = $CL $CM*;
146$CPcm = $CP $CM*;
147$EXcm = $EX $CM*;
148$EXXcm = $EXX $CM*;
149$GLcm = $GL $CM*;
150$HLcm = $HL $CM*;
151$HYcm = $HY $CM*;
152$H2cm = $H2 $CM*;
153$H3cm = $H3 $CM*;
154$IDcm = $ID $CM*;
155$INcm = $IN $CM*;
156$IScm = $IS $CM*;
157$JLcm = $JL $CM*;
158$JVcm = $JV $CM*;
159$JTcm = $JT $CM*;
160$NScm = $NS $CM*;
161$NSXcm = $NSX $CM*;
162$NUcm = $NU $CM*;
163$OPcm = $OP $CM*;
164$POcm = $PO $CM*;
165$POXcm = $POX $CM*;
166$PRcm = $PR $CM*;
167$PRXcm = $PRX $CM*;
168$QUcm = $QU $CM*;
169$RIcm = $RI $CM*;
170$SYcm = $SY $CM*;
171$WJcm = $WJ $CM*;
172
173## -------------------------------------------------
174
175!!forward;
176
177#
178#  Each class of character can stand by itself as an unbroken token, with trailing combining stuff
179#
180$ALPlus $CM+;
181$BA $CM+;
182$BAX $CM+;
183$BB $CM+;
184$B2 $CM+;
185$CL $CM+;
186$CP $CM+;
187$EX $CM+;
188$EXX $CM+;
189$GL $CM+;
190$HL $CM+;
191$HY $CM+;
192$H2 $CM+;
193$H3 $CM+;
194$ID $CM+;
195$IN $CM+;
196$IS $CM+;
197$JL $CM+;
198$JV $CM+;
199$JT $CM+;
200$NS $CM+;
201$NSX $CM+;
202$NU $CM+;
203$OP $CM+;
204$PO $CM+;
205$POX $CM+;
206$PR $CM+;
207$PRX $CM+;
208$QU $CM+;
209$RI $CM+;
210$SY $CM+;
211$WJ $CM+;
212
213#
214# CAN_CM  is the set of characters that may combine with CM combining chars.
215#         Note that Linebreak UAX 14's concept of a combining char and the rules
216#         for what they can combine with are _very_ different from the rest of Unicode.
217#
218#         Note that $CM itself is left out of this set.  If CM is needed as a base
219#         it must be listed separately in the rule.
220#
221$CAN_CM  = [^$SP $BK $CR $LF $NL $ZW $CM];       # Bases that can   take CMs
222$CANT_CM = [ $SP $BK $CR $LF $NL $ZW $CM];       # Bases that can't take CMs
223
224#
225# AL_FOLLOW  set of chars that can unconditionally follow an AL
226#            Needed in rules where stand-alone $CM s are treated as AL.
227#            Chaining is disabled with CM because it causes other failures,
228#            so for this one case we need to manually list out longer sequences.
229#
230$AL_FOLLOW_NOCM = [$BK $CR $LF $NL $ZW $SP];
231$AL_FOLLOW_CM   = [$CL $CP $EX $EXX $HL $IS $SY $WJ $GL $OP $QU $BA $BAX $HY $NS $NSX $IN $NU $ALPlus];
232$AL_FOLLOW      = [$AL_FOLLOW_NOCM $AL_FOLLOW_CM];
233
234
235#
236#  Rule LB 4, 5    Mandatory (Hard) breaks.
237#
238$LB4Breaks    = [$BK $CR $LF $NL];
239$LB4NonBreaks = [^$BK $CR $LF $NL];
240$CR $LF {100};
241
242#
243#  LB 6    Do not break before hard line breaks.
244#
245$LB4NonBreaks?  $LB4Breaks {100};    # LB 5  do not break before hard breaks.
246$CAN_CM $CM*    $LB4Breaks {100};
247$CM+            $LB4Breaks {100};
248
249# LB 7         x SP
250#              x ZW
251$LB4NonBreaks [$SP $ZW];
252$CAN_CM $CM*  [$SP $ZW];
253$CM+          [$SP $ZW];
254
255#
256# LB 8         Break after zero width space
257#              TODO:  ZW SP* <break>
258#              An engine change is required to write the reverse rule for this.
259#              For now, leave the Unicode 5.2 rule, ZW <break>
260#
261$LB8Breaks    = [$LB4Breaks $ZW];
262$LB8NonBreaks = [[$LB4NonBreaks] - [$ZW]];
263
264
265# LB 9     Combining marks.      X   $CM needs to behave like X, where X is not $SP, $BK $CR $LF $NL
266#                                $CM not covered by the above needs to behave like $AL
267#                                See definition of $CAN_CM.
268
269$CAN_CM $CM+;                   #  Stick together any combining sequences that don't match other rules.
270$CM+;
271
272#
273# LB 11  Do not break before or after WORD JOINER & related characters.
274#
275$CAN_CM $CM*  $WJcm;
276$LB8NonBreaks $WJcm;
277$CM+          $WJcm;
278
279$WJcm $CANT_CM;
280$WJcm $CAN_CM $CM*;
281
282#
283# LB 12  Do not break after NBSP and related characters.
284#         GL  x
285#
286$GLcm $CAN_CM $CM*;
287$GLcm $CANT_CM;
288
289#
290# LB 12a  Do not break before NBSP and related characters ...
291#            [^SP BA HY] x GL
292#
293[[$LB8NonBreaks] - [$SP $BA $BAX $HY]] $CM* $GLcm;
294$CM+ GLcm;
295
296
297
298#
299# LB 13   Don't break before ']' or '!' or ';' or '/', even after spaces.
300#
301# Do not include $EXX here
302$LB8NonBreaks $CL;
303$CAN_CM $CM*  $CL;
304$CM+          $CL;              # by rule 10, stand-alone CM behaves as AL
305
306$LB8NonBreaks $CP;
307$CAN_CM $CM*  $CP;
308$CM+          $CP;              # by rule 10, stand-alone CM behaves as AL
309
310$LB8NonBreaks $EX;
311$CAN_CM $CM*  $EX;
312$CM+          $EX;              # by rule 10, stand-alone CM behaves as AL
313
314$LB8NonBreaks $IS;
315$CAN_CM $CM*  $IS;
316$CM+          $IS;              # by rule 10, stand-alone CM behaves as AL
317
318$LB8NonBreaks $SY;
319$CAN_CM $CM*  $SY;
320$CM+          $SY;              # by rule 10, stand-alone CM behaves as AL
321
322
323#
324# LB 14  Do not break after OP, even after spaces
325#
326$OPcm $SP* $CAN_CM $CM*;
327$OPcm $SP* $CANT_CM;
328
329$OPcm $SP+ $CM+ $AL_FOLLOW?;    # by rule 10, stand-alone CM behaves as AL
330
331# LB 15
332$QUcm $SP* $OPcm;
333
334# LB 16
335# Do not break between closing punctuation and $NS, even with intervening spaces
336# But DO allow a break between closing punctuation and $NSX, don't include it here
337($CLcm | $CPcm) $SP* $NScm;
338
339# LB 17
340$B2cm $SP* $B2cm;
341
342#
343# LB 18  Break after spaces.
344#
345$LB18NonBreaks = [$LB8NonBreaks - [$SP]];
346$LB18Breaks    = [$LB8Breaks $SP];
347
348
349# LB 19
350#         x QU
351$LB18NonBreaks $CM* $QUcm;
352$CM+                $QUcm;
353
354#         QU  x
355$QUcm .?;
356$QUcm $LB18NonBreaks $CM*;    # Don't let a combining mark go onto $CR, $BK, etc.
357                              #  TODO:  I don't think this rule is needed.
358
359
360# LB 20
361#        <break>  $CB
362#        $CB   <break>
363
364$LB20NonBreaks = [$LB18NonBreaks - $CB];
365
366# LB 21        x   (BA | HY | NS)
367#           BB x
368#
369# DO allow breaks here before $BAXcm and $NSXcm, so don't include them
370$LB20NonBreaks $CM* ($BAcm | $HYcm | $NScm);
371
372$BBcm [^$CB];                                  #  $BB  x
373$BBcm $LB20NonBreaks $CM*;
374
375# LB 21a Don't break after Hebrew + Hyphen
376#   HL (HY | BA) x
377#
378$HLcm ($HYcm | $BAcm | $BAXcm) [^$CB]?;
379
380# LB 21b (forward) Don't break between SY and HL
381# (break between HL and SY already disallowed by LB 13 above)
382$SYcm $HLcm;
383
384# LB 22
385($ALcm | $HLcm) $INcm;
386$CM+     $INcm;     #  by rule 10, any otherwise unattached CM behaves as AL
387$IDcm    $INcm;
388# $INcm  $INcm; # delete this rule for CSS loose
389$NUcm    $INcm;
390
391
392# LB 23
393# Do not include $POX here
394$IDcm  $POcm;
395$ALcm  $NUcm;       # includes $LB19
396$HLcm  $NUcm;
397$CM+   $NUcm;       # Rule 10, any otherwise unattached CM behaves as AL
398$NUcm  $ALcm;
399$NUcm  $HLcm;
400
401#
402# LB 24
403#
404# Do not include $PRX here
405$PRcm $IDcm;
406$PRcm ($ALcm | $HLcm);
407($POcm | $POXcm) ($ALcm | $HLcm);
408
409#
410# LB 25   Numbers.
411#
412# Here do not include $PRX at the beginning or $POX at the end
413($PRcm | $POcm | $POXcm)? ($OPcm | $HYcm)? $NUcm ($NUcm | $SYcm | $IScm)* ($CLcm | $CPcm)? ($PRcm | $PRXcm | $POcm)?;
414
415# LB 26  Do not break a Korean syllable
416#
417$JLcm ($JLcm | $JVcm | $H2cm | $H3cm);
418($JVcm | $H2cm) ($JVcm | $JTcm);
419($JTcm | $H3cm) $JTcm;
420
421# LB 27  Treat korean Syllable Block the same as ID  (don't break it)
422# Do not include $POX or $PRX here
423($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $INcm;
424($JLcm | $JVcm | $JTcm | $H2cm | $H3cm) $POcm;
425$PRcm ($JLcm | $JVcm | $JTcm | $H2cm | $H3cm);
426
427
428# LB 28   Do not break between alphabetics
429#
430($ALcm | $HLcm) ($ALcm | $HLcm);
431$CM+ ($ALcm | $HLcm);      # The $CM+ is from rule 10, an unattached CM is treated as AL
432
433# LB 29
434$IScm ($ALcm | $HLcm);
435
436# LB 30
437($ALcm | $HLcm | $NUcm) $OPcm;
438$CM+ $OPcm;         # The $CM+ is from rule 10, an unattached CM is treated as AL.
439$CPcm ($ALcm | $HLcm | $NUcm);
440
441# LB 30a  Do not break between regional indicators.
442$RIcm $RIcm;
443
444#
445#  Reverse Rules.
446#
447## -------------------------------------------------
448
449!!reverse;
450
451$CM+ $ALPlus;
452$CM+ $BA;
453$CM+ $BAX;
454$CM+ $BB;
455$CM+ $B2;
456$CM+ $CL;
457$CM+ $CP;
458$CM+ $EX;
459$CM+ $EXX;
460$CM+ $GL;
461$CM+ $HL;
462$CM+ $HY;
463$CM+ $H2;
464$CM+ $H3;
465$CM+ $ID;
466$CM+ $IN;
467$CM+ $IS;
468$CM+ $JL;
469$CM+ $JV;
470$CM+ $JT;
471$CM+ $NS;
472$CM+ $NSX;
473$CM+ $NU;
474$CM+ $OP;
475$CM+ $PO;
476$CM+ $POX;
477$CM+ $PR;
478$CM+ $PRX;
479$CM+ $QU;
480$CM+ $RI;
481$CM+ $SY;
482$CM+ $WJ;
483$CM+;
484
485
486#
487#  Sequences of the form  (shown forwards)
488#      [CANT_CM]  <break>  [CM]  [whatever]
489#  The CM needs to behave as an AL
490#
491$AL_FOLLOW $CM+ / (
492          [$BK $CR $LF $NL $ZW {eof}] |
493          $SP+ $CM+ $SP |
494          $SP+ $CM* ([^$OP $CM $SP] | [$AL {eof}]));   # if LB 14 will match, need to surpress this break.
495                                               #  LB14 says    OP SP* x .
496                                               #    becomes    OP SP* x AL
497                                               #    becomes    OP SP* x CM+ AL_FOLLOW
498                                               #
499                                               # Further note:  the $AL in [$AL {eof}] is only to work around
500                                               #                a rule compiler bug which complains about
501                                               #                empty sets otherwise.
502
503#
504#  Sequences of the form  (shown forwards)
505#      [CANT_CM]  <break> [CM]  <break>  [PR]
506#  The CM needs to behave as an AL
507#  This rule is concerned about getting the second of the two <breaks> in place.
508#
509
510[$PR $PRX  ] / $CM+ [$BK $CR $LF $NL $ZW $SP {eof}];
511
512
513
514# LB 4, 5, 5
515
516$LB4Breaks [$LB4NonBreaks-$CM];
517$LB4Breaks $CM+ $CAN_CM;
518$LF $CR;
519
520
521# LB 7         x SP
522#              x ZW
523[$SP $ZW] [$LB4NonBreaks-$CM];
524[$SP $ZW] $CM+ $CAN_CM;
525
526# LB 8 ZW SP* <break>
527#     TODO: to implement this, we need more than one look-ahead hard break in play at a time.
528#           Requires an engine enhancement.
529#   / $SP* $ZW
530
531# LB 9,10  Combining marks.
532#    X   $CM needs to behave like X, where X is not $SP or controls.
533#    $CM not covered by the above needs to behave like $AL
534# Stick together any combining sequences that don't match other rules.
535$CM+ $CAN_CM;
536
537
538# LB 11
539$CM* $WJ $CM* $CAN_CM;
540$CM* $WJ      [$LB8NonBreaks-$CM];
541
542     $CANT_CM $CM* $WJ;
543$CM* $CAN_CM  $CM* $WJ;
544
545# LB 12a
546#      [^SP BA HY] x GL
547#
548$CM* $GL $CM* [$LB8NonBreaks-[$CM $SP $BA $BAX $HY]];
549
550# LB 12
551#     GL  x
552#
553$CANT_CM $CM* $GL;
554$CM* $CAN_CM $CM* $GL;
555
556
557# LB 13
558# Do not include $EXX here
559$CL $CM+ $CAN_CM;
560$CP $CM+ $CAN_CM;
561$EX $CM+ $CAN_CM;
562$IS $CM+ $CAN_CM;
563$SY $CM+ $CAN_CM;
564
565$CL [$LB8NonBreaks-$CM];
566$CP [$LB8NonBreaks-$CM];
567$EX [$LB8NonBreaks-$CM];
568$IS [$LB8NonBreaks-$CM];
569$SY [$LB8NonBreaks-$CM];
570
571# Rule 13 & 14 taken together for an edge case.
572#   Match this, shown forward
573#     OP SP+  ($CM+ behaving as $AL) (CL | CP | EX | IS | IY)
574#   This really wants to chain at the $CM+ (which is acting as an $AL)
575#   except for $CM chaining being disabled.
576[$CL $CP $EX $IS $SY] $CM+ $SP+ $CM* $OP;
577
578# LB 14    OP SP* x
579#
580$CM* $CAN_CM    $SP* $CM* $OP;
581     $CANT_CM   $SP* $CM* $OP;
582$AL_FOLLOW? $CM+  $SP $SP* $CM* $OP;     #  by LB 10, behaves like $AL_FOLLOW? $AL $SP* $CM* $OP
583
584     $AL_FOLLOW_NOCM $CM+ $SP+ $CM* $OP;
585$CM* $AL_FOLLOW_CM   $CM+ $SP+ $CM* $OP;
586$SY $CM $SP+ $OP;   # TODO:  Experiment.  Remove.
587
588
589
590# LB 15
591$CM* $OP $SP* $CM* $QU;
592
593# LB 16
594# Don't include $NSX here
595$CM* $NS $SP* $CM* ($CL | $CP);
596
597# LB 17
598$CM* $B2 $SP* $CM* $B2;
599
600# LB 18  break after spaces
601#        Nothing explicit needed here.
602
603
604#
605# LB 19
606#
607$CM* $QU $CM* $CAN_CM;                                #   . x QU
608$CM* $QU      $LB18NonBreaks;
609
610
611$CM* $CAN_CM  $CM* $QU;                               #   QU x .
612     $CANT_CM $CM* $QU;
613
614#
615#  LB 20  Break before and after CB.
616#         nothing needed here.
617#
618
619# LB 21
620# Don't include $BAX or $NSX here
621$CM* ($BA | $HY | $NS) $CM* [$LB20NonBreaks-$CM];     #  . x (BA | HY | NS)
622
623$CM* [$LB20NonBreaks-$CM] $CM* $BB;                   #  BB x .
624[^$CB] $CM* $BB;                                      #
625
626# LB21a
627[^$CB] $CM* ($HY | $BA | $BAX) $CM* $HL;
628
629# LB21b (reverse)
630$CM* $HL $CM* $SY;
631
632# LB 22
633$CM* $IN $CM* ($ALPlus | $HL);
634$CM* $IN $CM* $ID;
635# $CM* $IN $CM* $IN; # delete this rule for CSS loose
636$CM* $IN $CM* $NU;
637
638# LB 23
639# Do not include $POX here
640$CM* $PO $CM* $ID;
641$CM* $NU $CM* ($ALPlus | $HL);
642$CM* ($ALPlus | $HL) $CM* $NU;
643
644# LB 24
645# Do not include $PRX here
646$CM* $ID $CM* $PR;
647$CM* ($ALPlus | $HL) $CM* $PR;
648$CM* ($ALPlus | $HL) $CM* ($PO | $POX);
649
650
651# LB 25
652# Here do not include $POX at the beginning or $PRX at the end
653($CM* ($PR | $PRX | $PO))? ($CM* ($CL | $CP))? ($CM* ($NU | $IS | $SY))* $CM* $NU ($CM* ($OP | $HY))? ($CM* ($PR | $PO | $POX))?;
654
655# LB 26
656$CM* ($H3 | $H2 | $JV | $JL) $CM* $JL;
657$CM* ($JT | $JV) $CM* ($H2 | $JV);
658$CM* $JT $CM* ($H3 | $JT);
659
660# LB 27
661# Do not include $POX or $PRX here
662$CM* $IN $CM* ($H3 | $H2 | $JT | $JV | $JL);
663$CM* $PO $CM* ($H3 | $H2 | $JT | $JV | $JL);
664$CM* ($H3 | $H2 | $JT | $JV | $JL) $CM* $PR;
665
666# LB 28
667$CM* ($ALPlus | $HL) $CM* ($ALPlus | $HL);
668
669
670# LB 29
671$CM* ($ALPlus | $HL) $CM* $IS;
672
673# LB 30
674$CM* $OP $CM* ($ALPlus | $HL | $NU);
675$CM* ($ALPlus | $HL | $NU) $CM* $CP;
676
677# LB 30a
678$CM* $RI $CM* $RI;
679
680## -------------------------------------------------
681
682!!safe_reverse;
683
684# LB 9
685$CM+ [^$CM $BK $CR $LF $NL $ZW $SP];
686$CM+ $SP / .;
687
688# LB 14
689$SP+ $CM* $OP;
690
691# LB 15
692$SP+ $CM* $QU;
693
694# LB 16
695$SP+ $CM* ($CL | $CP);
696
697# LB 17
698$SP+ $CM* $B2;
699
700# LB 21
701$CM* ($HY | $BA) $CM* $HL;
702
703# LB 25
704($CM* ($IS | $SY))+ $CM* $NU;
705($CL | $CP) $CM* ($NU | $IS | $SY);
706
707# For dictionary-based break
708$dictionary $dictionary;
709
710## -------------------------------------------------
711
712!!safe_forward;
713
714# Skip forward over all character classes that are involved in
715#   rules containing patterns with possibly more than one char
716#   of context.
717#
718#  It might be slightly more efficient to have specific rules
719#  instead of one generic one, but only if we could
720#  turn off rule chaining.  We don't want to move more
721#  than necessary.
722#
723[$CM $OP $QU $CL $CP $B2 $PR $PRX $HY $BA $SP $dictionary]+ [^$CM $OP $QU $CL $CP $B2 $PR $PRX $HY $BA $dictionary];
724$dictionary $dictionary;
725
726