Implement Unicode line breaking algorithm
Signed-off-by: Drew DeVault <sir@cmpwn.com>
This commit is contained in:
parent
c56f5d40af
commit
9c73c17238
6 changed files with 1388 additions and 1101 deletions
33
cmd/linebreak/main.ha
Normal file
33
cmd/linebreak/main.ha
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
use fmt;
|
||||||
|
use os;
|
||||||
|
use unicode;
|
||||||
|
|
||||||
|
export fn main() void = {
|
||||||
|
const input = os::args[1];
|
||||||
|
|
||||||
|
fmt::println(input)!;
|
||||||
|
|
||||||
|
let ix = 0u;
|
||||||
|
const lb = unicode::new_line_breaker(input);
|
||||||
|
for (const (pos, mand) => unicode::next_line_break(&lb)) {
|
||||||
|
for (ix < pos; ix += 1) {
|
||||||
|
fmt::print(' ')!;
|
||||||
|
};
|
||||||
|
ix += 1;
|
||||||
|
|
||||||
|
if (mand) {
|
||||||
|
fmt::println('|')!;
|
||||||
|
} else {
|
||||||
|
fmt::print('^')!;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fmt::println()!;
|
||||||
|
fmt::println()!;
|
||||||
|
|
||||||
|
fmt::println("Line break opportunities:")!;
|
||||||
|
const lb = unicode::new_line_breaker(input);
|
||||||
|
for (const (pos, mand) => unicode::next_line_break(&lb)) {
|
||||||
|
fmt::printfln("- {} {}", pos, if (mand) "(mandatory)" else "")!;
|
||||||
|
};
|
||||||
|
};
|
|
@ -90,11 +90,10 @@ EASTASIANWIDTH_NAMES = [ "F", "H", "W", "Na", "A", "N" ]
|
||||||
MANDATORY_LINE_BREAKS = [ "BK", "CR", "LF", "NL" ]
|
MANDATORY_LINE_BREAKS = [ "BK", "CR", "LF", "NL" ]
|
||||||
|
|
||||||
LINE_BREAKS = [
|
LINE_BREAKS = [
|
||||||
"XX",
|
"XX", "AI", "BK", "CJ", "CR", "LF", "NL", "SA", "SG", "SP", "OP", "CL",
|
||||||
"AI", "AL", "B2", "BA", "BB", "BK", "CB", "CJ", "CL", "CM", "CP", "CR",
|
"CP", "QU", "GL", "NS", "EX", "SY", "IS", "PR", "PO", "NU", "AL", "HL",
|
||||||
"EB", "EM", "EX", "GL", "H2", "H3", "HL", "HY", "ID", "IN", "IS", "JL",
|
"ID", "IN", "HY", "BA", "BB", "B2", "ZW", "CM", "WJ", "H2", "H3", "JL",
|
||||||
"JT", "JV", "LF", "NL", "NS", "NU", "OP", "PO", "PR", "QU", "RI", "SA",
|
"JV", "JT", "RI", "EB", "EM", "ZWJ", "CB",
|
||||||
"SG", "SP", "SY", "WJ", "ZW", "ZWJ",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
SCRIPT_NAMES = [
|
SCRIPT_NAMES = [
|
||||||
|
|
192
unicode/linebreak.ha
Normal file
192
unicode/linebreak.ha
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
use strings;
|
||||||
|
|
||||||
|
export type line_breaker = struct {
|
||||||
|
input: str,
|
||||||
|
iter: strings::iterator,
|
||||||
|
// Current position
|
||||||
|
pos: uint,
|
||||||
|
// Previous position
|
||||||
|
ppos: uint,
|
||||||
|
// Current line break class
|
||||||
|
cur: line_break,
|
||||||
|
// Next line break class
|
||||||
|
next: line_break,
|
||||||
|
// State for specific rules
|
||||||
|
lb8a: bool,
|
||||||
|
lb21a: bool,
|
||||||
|
lb30a: uint,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Creates a new line breaking algorithm state machine. See [[next_line_break]]
|
||||||
|
// to enumerate the line break opportunities in the input string.
|
||||||
|
export fn new_line_breaker(input: str) line_breaker = {
|
||||||
|
return line_breaker {
|
||||||
|
input = input,
|
||||||
|
...
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the next line break opportunity as a tuple of the rune-wise index of
|
||||||
|
// the opportunity in the input string and a boolean indicating if the line
|
||||||
|
// break is mandatory at this location. The line break opportunity directly
|
||||||
|
// precedes the index returned from this function.
|
||||||
|
//
|
||||||
|
// Hello world!
|
||||||
|
// ^ Line break opportunity at index 6
|
||||||
|
export fn next_line_break(lb: *line_breaker) ((uint, bool) | done) = {
|
||||||
|
if (lb.pos == 0) {
|
||||||
|
if (len(lb.input) == 0) {
|
||||||
|
return done; // special case
|
||||||
|
};
|
||||||
|
|
||||||
|
lb.iter = strings::iter(lb.input);
|
||||||
|
|
||||||
|
let class = next_lb1_class(lb) as line_break;
|
||||||
|
class = resolve_lb2_class(class);
|
||||||
|
lb.cur = class;
|
||||||
|
lb.next = class;
|
||||||
|
lb.lb8a = class == line_break::ZWJ;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const next => next_lb1_class(lb)) {
|
||||||
|
const prev = lb.next;
|
||||||
|
lb.next = next;
|
||||||
|
lb.ppos = lb.pos;
|
||||||
|
defer lb.pos += 1;
|
||||||
|
|
||||||
|
const mandatory = lb.cur == line_break::BK
|
||||||
|
|| (lb.cur == line_break::CR
|
||||||
|
&& lb.next != line_break::LF);
|
||||||
|
if (mandatory) {
|
||||||
|
lb.cur = resolve_lb2_class(next);
|
||||||
|
return (lb.pos + 1, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
lb.lb8a = next == line_break::ZWJ;
|
||||||
|
|
||||||
|
let can_break = lb_simple_case(lb);
|
||||||
|
match (can_break) {
|
||||||
|
case bool => void;
|
||||||
|
case void =>
|
||||||
|
can_break = lb_complex_case(lb, prev);
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(can_break is bool);
|
||||||
|
const can_break = can_break as bool;
|
||||||
|
if (can_break) {
|
||||||
|
return (lb.pos + 1, false);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return done;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Applies LB1 suggested rules for resolving context-dependent classes.
|
||||||
|
fn next_lb1_class(lb: *line_breaker) (line_break | done) = {
|
||||||
|
const rn = match (strings::next(&lb.iter)) {
|
||||||
|
case let rn: rune =>
|
||||||
|
yield rn;
|
||||||
|
case done =>
|
||||||
|
return done;
|
||||||
|
};
|
||||||
|
|
||||||
|
const class = rune_line_break(rn);
|
||||||
|
switch (class) {
|
||||||
|
case line_break::AI, line_break::SG, line_break::XX =>
|
||||||
|
return line_break::AL;
|
||||||
|
case line_break::SA =>
|
||||||
|
switch (rune_gc(rn)) {
|
||||||
|
case gc::Mn, gc::Mc =>
|
||||||
|
return line_break::CM;
|
||||||
|
case =>
|
||||||
|
return line_break::AL;
|
||||||
|
};
|
||||||
|
case line_break::CJ =>
|
||||||
|
return line_break::NS;
|
||||||
|
case =>
|
||||||
|
return class;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Applies LB2 suggested rules for resolving the start-of-text line-break class.
|
||||||
|
fn resolve_lb2_class(lb: line_break) line_break = {
|
||||||
|
switch (lb) {
|
||||||
|
case line_break::LF, line_break::NL =>
|
||||||
|
return line_break::BK;
|
||||||
|
case line_break::SP =>
|
||||||
|
return line_break::WJ;
|
||||||
|
case =>
|
||||||
|
return lb;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this is a simple case, return whether or not this is a break opportunity
|
||||||
|
// as a boolean. Returns void for special cases.
|
||||||
|
fn lb_simple_case(lb: *line_breaker) (bool | void) = {
|
||||||
|
switch (lb.next) {
|
||||||
|
case line_break::SP =>
|
||||||
|
return false;
|
||||||
|
case line_break::BK, line_break::LF, line_break::NL =>
|
||||||
|
lb.cur = line_break::BK;
|
||||||
|
return false;
|
||||||
|
case line_break::CR =>
|
||||||
|
lb.cur = line_break::CR;
|
||||||
|
return false;
|
||||||
|
case =>
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handles more complex rules, including pair table lookups via
|
||||||
|
// linebreak_table.ha.
|
||||||
|
fn lb_complex_case(lb: *line_breaker, prev: line_break) bool = {
|
||||||
|
let can_break = false;
|
||||||
|
|
||||||
|
const ucur = lb.cur: uint - line_break::OP: uint;
|
||||||
|
const unext = lb.next: uint - line_break::OP: uint;
|
||||||
|
if (ucur < len(lb_pairs) && unext < len(lb_pairs[0])) {
|
||||||
|
switch (lb_pairs[ucur][unext]) {
|
||||||
|
case bo::DI => // Direct break
|
||||||
|
can_break = true;
|
||||||
|
case bo::IN => // Indirect break opportunity
|
||||||
|
can_break = prev == line_break::SP;
|
||||||
|
case bo::CI => // Indirect opportunity for combining marks
|
||||||
|
can_break = prev == line_break::SP;
|
||||||
|
if (!can_break) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
case bo::CP => // Prohibited for combining marks
|
||||||
|
if (prev != line_break::SP) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
case bo::PR => void;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Rule LB8a
|
||||||
|
if (lb.lb8a) {
|
||||||
|
can_break = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Rule LB21a
|
||||||
|
if (lb.lb21a && (lb.cur == line_break::HY || lb.cur == line_break::BA)) {
|
||||||
|
can_break = false;
|
||||||
|
lb.lb21a = false;
|
||||||
|
} else {
|
||||||
|
lb.lb21a = lb.cur == line_break::HL;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Rule LB30a
|
||||||
|
if (lb.cur == line_break::RI) {
|
||||||
|
lb.lb30a += 1;
|
||||||
|
if (lb.lb30a == 2 && lb.next == line_break::RI) {
|
||||||
|
can_break = true;
|
||||||
|
lb.lb30a = 0;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
lb.lb30a = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
lb.cur = lb.next;
|
||||||
|
return can_break;
|
||||||
|
};
|
63
unicode/linebreak_table.ha
Normal file
63
unicode/linebreak_table.ha
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// Break opportunity
|
||||||
|
type bo = enum {
|
||||||
|
// Direct opportunity
|
||||||
|
DI,
|
||||||
|
// Indirect opportunity
|
||||||
|
IN,
|
||||||
|
// Indirect opportunity for combining marks
|
||||||
|
CI,
|
||||||
|
// Prohibited break for combining marks
|
||||||
|
CP,
|
||||||
|
// Prohibited break
|
||||||
|
PR,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Based on JavaScript implementation here:
|
||||||
|
//
|
||||||
|
// https://github.com/foliojs/linebreak/blob/master/src/pairs.js
|
||||||
|
//
|
||||||
|
// This is itself based on the example pair table from Unicode, which was last
|
||||||
|
// published in revision 37 of the line break algorithm, and has since been
|
||||||
|
// touched up by the JavaScript maintainers to incorporate later changes to the
|
||||||
|
// algorithm.
|
||||||
|
//
|
||||||
|
// - ZWJ special processing for LB8a of Revision 41
|
||||||
|
// - CB manually added as per Rule LB20
|
||||||
|
// - CL, CP, NS, SY, IS, PR, PO, HY, BA, B2 and RI manually adjusted as per LB22 of Revision 45
|
||||||
|
const lb_pairs = [
|
||||||
|
//OP , CL , CP , QU , GL , NS , EX , SY , IS , PR , PO , NU , AL , HL , ID , IN , HY , BA , BB , B2 , ZW , CM , WJ , H2 , H3 , JL , JV , JT , RI , EB , EM , ZWJ , CB
|
||||||
|
[bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::CP, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR, bo::PR], // OP
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // CL
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // CP
|
||||||
|
[bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::PR, bo::CI, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN], // QU
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::PR, bo::CI, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN], // GL
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // NS
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // EX
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::IN, bo::DI, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // SY
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // IS
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI], // PR
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // PO
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // NU
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // AL
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // HL
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // ID
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // IN
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::DI, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // HY
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::DI, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // BA
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::PR, bo::CI, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI], // BB
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::PR, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // B2
|
||||||
|
[bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI], // ZW
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // CM
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::PR, bo::CI, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN], // WJ
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // H2
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // H3
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // JL
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // JV
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // JT
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI, bo::DI, bo::IN, bo::DI], // RI
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::DI], // EB
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::DI, bo::IN, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // EM
|
||||||
|
[bo::IN, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::PR, bo::PR, bo::PR, bo::IN, bo::IN, bo::IN, bo::IN, bo::IN, bo::DI, bo::IN, bo::IN, bo::IN, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI], // ZWJ
|
||||||
|
[bo::DI, bo::PR, bo::PR, bo::IN, bo::IN, bo::DI, bo::PR, bo::PR, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::PR, bo::CI, bo::PR, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::DI, bo::IN, bo::DI] // CB
|
||||||
|
];
|
||||||
|
|
|
@ -513,47 +513,47 @@ export fn script_code(sc: script) const str = {
|
||||||
export type line_break = enum u8 {
|
export type line_break = enum u8 {
|
||||||
XX,
|
XX,
|
||||||
AI,
|
AI,
|
||||||
AL,
|
|
||||||
B2,
|
|
||||||
BA,
|
|
||||||
BB,
|
|
||||||
BK,
|
BK,
|
||||||
CB,
|
|
||||||
CJ,
|
CJ,
|
||||||
CL,
|
|
||||||
CM,
|
|
||||||
CP,
|
|
||||||
CR,
|
CR,
|
||||||
EB,
|
|
||||||
EM,
|
|
||||||
EX,
|
|
||||||
GL,
|
|
||||||
H2,
|
|
||||||
H3,
|
|
||||||
HL,
|
|
||||||
HY,
|
|
||||||
ID,
|
|
||||||
IN,
|
|
||||||
IS,
|
|
||||||
JL,
|
|
||||||
JT,
|
|
||||||
JV,
|
|
||||||
LF,
|
LF,
|
||||||
NL,
|
NL,
|
||||||
NS,
|
|
||||||
NU,
|
|
||||||
OP,
|
|
||||||
PO,
|
|
||||||
PR,
|
|
||||||
QU,
|
|
||||||
RI,
|
|
||||||
SA,
|
SA,
|
||||||
SG,
|
SG,
|
||||||
SP,
|
SP,
|
||||||
|
OP,
|
||||||
|
CL,
|
||||||
|
CP,
|
||||||
|
QU,
|
||||||
|
GL,
|
||||||
|
NS,
|
||||||
|
EX,
|
||||||
SY,
|
SY,
|
||||||
WJ,
|
IS,
|
||||||
|
PR,
|
||||||
|
PO,
|
||||||
|
NU,
|
||||||
|
AL,
|
||||||
|
HL,
|
||||||
|
ID,
|
||||||
|
IN,
|
||||||
|
HY,
|
||||||
|
BA,
|
||||||
|
BB,
|
||||||
|
B2,
|
||||||
ZW,
|
ZW,
|
||||||
|
CM,
|
||||||
|
WJ,
|
||||||
|
H2,
|
||||||
|
H3,
|
||||||
|
JL,
|
||||||
|
JV,
|
||||||
|
JT,
|
||||||
|
RI,
|
||||||
|
EB,
|
||||||
|
EM,
|
||||||
ZWJ,
|
ZWJ,
|
||||||
|
CB,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the [[line_break]] classification corresponding to this rune.
|
// Returns the [[line_break]] classification corresponding to this rune.
|
||||||
|
|
2132
unicode/ucd_gen.ha
2132
unicode/ucd_gen.ha
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue