#! /usr/bin/gawk # -*- coding: utf-8 -*- # Last edited on 2026-09-29 17:54:07 by stolfi # To be included in factor-field-general etc. function factor_text(x, y,e,xold) { # Factors a Chinese pinyin text by placing "{}" around # the initial and final consonants (if present), each # medial vowel separately. # Allows tone dicritics or numeric tones. # If there is a numeric tone, outputs it as a separate element. # If there is a disamb suffix ".{digit}", returns it as # a separate element. # Reduces all chars to lowercase. # If the word is all '?', returns '{?}' # Does not support the "ê" letter, plain or in any tone. xold = x # printf "%s -> ", ("\"" x "\"") > "/dev/stderr"; if (match(/^[?]+$/, x)) { return "{?}"; } x = tolower(x) # The vowel "ü"" can be written "u:" in some # contexts. gsub(/u:/, "ü", x) if (match(x, /[:\^]/)) { data_error(("invalid use of :/^ in '" xold "'")); } # Remove the pointless spelling conventions "wu" and "yi" x = gensub(/^[w]([uüūǖùǜúǘǔǚ])/, "\\1", "g", x) x = gensub(/^[y]([iīìíǐ])/, "\\1", "g", x) # Convert other initial "y" and "w" to "i" and "u": x = gensub(/^[w]([aeioāēīōàèìòáéíóǎěǐǒ])/, "u\\1", "g", x) x = gensub(/^[y]([aeouüüāēōūǖàèòùǜáéóúǘǎěǒǔǚ])/, "i\\1", "g", x) if (match(x, /^[wy]/)) { data_error(("invalid use of w/y in '" xold "'")); } y = ""; # Extract the initial consonant, if any. Note that # the syllable "ng" has only the final part. if (! match(x, /^ng$)/)) { if (match(x, /^([csz][h]|[b-df-hj-np-txz])/)) { e = substr(x, RSTART,RLENGTH); x = substr(x, RSTART+RLENGTH); y = (y "{" e "}"); } } # printf "%s -> ", ("\"" y x "\"") > "/dev/stderr"; # Extract the syllable vowels. # Note that "yi" and "wu" have been mapped to "i" and "u": while (match(x, /^[aeiouüywüāēīōūǖàèìòùǜáéíóúǘǎěǐǒǔǚ]/)) { e = substr(x, RSTART,RLENGTH); x = substr(x, RSTART+RLENGTH); y = (y "{" e "}"); } # printf "%s -> ", ("\"" y x "\"") > "/dev/stderr"; # Extract the syllable coda, if any. if (match(x, /^[n][g]?|[r]/)) { e = substr(x, RSTART,RLENGTH); x = substr(x, RSTART+RLENGTH); y = (y "{" e "}"); } # printf "%s -> ", ("\"" y x "\"") > "/dev/stderr"; # Parse a numeric tone code (a digit) if present. if (match(x, /^[0-9]/)) { e = substr(x, RSTART,RLENGTH); x = substr(x, RSTART+RLENGTH); y = (y "{" e "}"); } # printf "%s -> ", ("\"" y x "\"") > "/dev/stderr"; # Parse the disambiguating suffix (a `.' followed by one or more digits, # if present. if (match(x, /^[.][0-9]+/)) { e = substr(x, RSTART,RLENGTH); x = substr(x, RSTART+RLENGTH); y = (y "{" e "}"); } # printf "%s -> ", ("\"" y x "\"") > "/dev/stderr"; # Now we must have consumed all of "x": if (x != "") { data_error(("bad pinyin word \"" y x "\"")); } # printf "%s\n", ("\"" y "\"") > "/dev/stderr"; return y; }