calliope-ts 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -13
- package/dist/caesura.d.ts +33 -0
- package/dist/caesura.d.ts.map +1 -0
- package/dist/caesura.js +202 -0
- package/dist/calliope/boundaries.d.ts +19 -0
- package/dist/calliope/boundaries.d.ts.map +1 -0
- package/dist/calliope/boundaries.js +182 -0
- package/dist/calliope/bracketing.d.ts +11 -0
- package/dist/calliope/bracketing.d.ts.map +1 -0
- package/dist/calliope/bracketing.js +416 -0
- package/dist/calliope/deps.d.ts +4 -0
- package/dist/calliope/deps.d.ts.map +1 -0
- package/dist/calliope/deps.js +181 -0
- package/dist/calliope/engine.d.ts +3 -0
- package/dist/calliope/engine.d.ts.map +1 -0
- package/dist/calliope/engine.js +71 -0
- package/dist/calliope/feats.d.ts +9 -0
- package/dist/calliope/feats.d.ts.map +1 -0
- package/dist/calliope/feats.js +45 -0
- package/dist/calliope/names.d.ts +7 -0
- package/dist/calliope/names.d.ts.map +1 -0
- package/dist/calliope/names.js +42 -0
- package/dist/calliope/postag.d.ts +8 -0
- package/dist/calliope/postag.d.ts.map +1 -0
- package/dist/calliope/postag.js +250 -0
- package/dist/calliope/prosodic.d.ts +3 -0
- package/dist/calliope/prosodic.d.ts.map +1 -0
- package/dist/calliope/prosodic.js +275 -0
- package/dist/calliope/relstress.d.ts +4 -0
- package/dist/calliope/relstress.d.ts.map +1 -0
- package/dist/calliope/relstress.js +688 -0
- package/dist/calliope/stressrules.d.ts +28 -0
- package/dist/calliope/stressrules.d.ts.map +1 -0
- package/dist/calliope/stressrules.js +147 -0
- package/dist/calliope/syntax.d.ts +38 -0
- package/dist/calliope/syntax.d.ts.map +1 -0
- package/dist/calliope/syntax.js +234 -0
- package/dist/calliope/udpos.d.ts +13 -0
- package/dist/calliope/udpos.d.ts.map +1 -0
- package/dist/calliope/udpos.js +156 -0
- package/dist/clio/caesura.d.ts +27 -0
- package/dist/clio/caesura.d.ts.map +1 -0
- package/dist/clio/caesura.js +148 -0
- package/dist/clio/depfix.d.ts +13 -0
- package/dist/clio/depfix.d.ts.map +1 -0
- package/dist/clio/depfix.js +84 -0
- package/dist/clio/display.d.ts +32 -0
- package/dist/clio/display.d.ts.map +1 -0
- package/dist/clio/display.js +976 -0
- package/dist/clio/engine.d.ts +3 -0
- package/dist/clio/engine.d.ts.map +1 -0
- package/dist/clio/engine.js +28 -0
- package/dist/clio/parser.d.ts +10 -0
- package/dist/clio/parser.d.ts.map +1 -0
- package/dist/clio/parser.js +696 -0
- package/dist/clio/phonological.d.ts +41 -0
- package/dist/clio/phonological.d.ts.map +1 -0
- package/dist/clio/phonological.js +788 -0
- package/dist/clio/phrasestress.d.ts +6 -0
- package/dist/clio/phrasestress.d.ts.map +1 -0
- package/dist/clio/phrasestress.js +106 -0
- package/dist/clio/pipeline.d.ts +11 -0
- package/dist/clio/pipeline.d.ts.map +1 -0
- package/dist/clio/pipeline.js +147 -0
- package/dist/clio/rhyme.d.ts +65 -0
- package/dist/clio/rhyme.d.ts.map +1 -0
- package/dist/clio/rhyme.js +761 -0
- package/dist/clio/scandroid.d.ts +17 -0
- package/dist/clio/scandroid.d.ts.map +1 -0
- package/dist/clio/scandroid.js +435 -0
- package/dist/clio/scansion.d.ts +46 -0
- package/dist/clio/scansion.d.ts.map +1 -0
- package/dist/clio/scansion.js +1086 -0
- package/dist/clio/semantics.d.ts +44 -0
- package/dist/clio/semantics.d.ts.map +1 -0
- package/dist/clio/semantics.js +139 -0
- package/dist/clio/stress.d.ts +83 -0
- package/dist/clio/stress.d.ts.map +1 -0
- package/dist/clio/stress.js +1737 -0
- package/dist/clio/tagfix.d.ts +6 -0
- package/dist/clio/tagfix.d.ts.map +1 -0
- package/dist/clio/tagfix.js +101 -0
- package/dist/display.d.ts +0 -6
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +322 -141
- package/dist/engine.d.ts +9 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +12 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +169 -26
- package/dist/parser.d.ts +3 -3
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +320 -563
- package/dist/phonological.d.ts +1 -1
- package/dist/phonological.d.ts.map +1 -1
- package/dist/phonological.js +73 -4
- package/dist/phrasestress.d.ts +6 -0
- package/dist/phrasestress.d.ts.map +1 -0
- package/dist/phrasestress.js +106 -0
- package/dist/rhyme.d.ts +40 -1
- package/dist/rhyme.d.ts.map +1 -1
- package/dist/rhyme.js +435 -7
- package/dist/scansion.d.ts +9 -0
- package/dist/scansion.d.ts.map +1 -1
- package/dist/scansion.js +145 -18
- package/dist/semantics.d.ts +44 -0
- package/dist/semantics.d.ts.map +1 -0
- package/dist/semantics.js +139 -0
- package/dist/stress.d.ts +127 -4
- package/dist/stress.d.ts.map +1 -1
- package/dist/stress.js +834 -61
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/caesura.ts +201 -0
- package/src/calliope/boundaries.ts +190 -0
- package/src/calliope/bracketing.ts +390 -0
- package/src/calliope/deps.ts +160 -0
- package/src/calliope/engine.ts +77 -0
- package/src/calliope/feats.ts +46 -0
- package/src/calliope/names.ts +44 -0
- package/src/calliope/postag.ts +253 -0
- package/src/calliope/prosodic.ts +262 -0
- package/src/calliope/relstress.ts +645 -0
- package/src/calliope/stressrules.ts +147 -0
- package/src/calliope/syntax.ts +218 -0
- package/src/calliope/udpos.ts +152 -0
- package/src/clio/caesura.ts +145 -0
- package/src/clio/depfix.ts +88 -0
- package/src/clio/display.ts +1042 -0
- package/src/clio/engine.ts +38 -0
- package/src/clio/parser.ts +845 -0
- package/src/clio/phonological.ts +849 -0
- package/src/clio/phrasestress.ts +108 -0
- package/src/clio/pipeline.ts +154 -0
- package/src/clio/rhyme.ts +740 -0
- package/src/clio/scandroid.ts +434 -0
- package/src/clio/scansion.ts +1130 -0
- package/src/clio/semantics.ts +134 -0
- package/src/clio/stress.ts +1731 -0
- package/src/clio/tagfix.ts +104 -0
- package/src/display.ts +321 -137
- package/src/engine.ts +22 -0
- package/src/index.ts +176 -32
- package/src/parser.ts +346 -682
- package/src/phonological.ts +72 -4
- package/src/phrasestress.ts +108 -0
- package/src/rhyme.ts +428 -8
- package/src/scansion.ts +136 -15
- package/src/semantics.ts +134 -0
- package/src/stress.ts +794 -64
- package/src/types.ts +39 -4
- package/tests/DataForHayesLinesOnly.txt +364 -0
- package/tests/DataForHayesStressSymbolsRevised.txt +728 -0
- package/tests/basic.test.ts +443 -37
- package/tests/bench-hayes.mjs +72 -0
- package/tests/wagner-stress.test.ts +188 -0
- package/vitest.config.ts +0 -15
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
// calliope/prosodic.ts — the Match-Theory prosodic hierarchy for Calliope.
|
|
2
|
+
//
|
|
3
|
+
// Builds the κ (clitic group) / ϕ (phonological phrase) / ι (intonational unit)
|
|
4
|
+
// structure from the canonical dependency relations and the REAL utterance
|
|
5
|
+
// boundaries — replacing the legacy builder (phonological.ts), which split an IU
|
|
6
|
+
// at every comma and grouped phrases off the constituent tree. The corrections,
|
|
7
|
+
// per McAleese A1/A2 and the maintainer's critique:
|
|
8
|
+
//
|
|
9
|
+
// ι only at genuine intonational breaks: terminal punctuation (. ? !), colon,
|
|
10
|
+
// semicolon, and parentheticals. A plain COMMA is NOT an ι — it is a minor
|
|
11
|
+
// ϕ break. (This is the "utterance boundaries, not line breaks / not every
|
|
12
|
+
// comma" fix.)
|
|
13
|
+
// ϕ at: a comma; the head of an oblique PP (a preposition opens a new phrase —
|
|
14
|
+
// "…compare thee | to a summer's day"); each coordinate conjunct; a clause
|
|
15
|
+
// complement (CCOMP/XCOMP/ADVCL); and the junction between a full nominal
|
|
16
|
+
// SUBJECT and its predicate verb.
|
|
17
|
+
// κ a content head plus its function words by DIRECTION: determiners, case
|
|
18
|
+
// markers/prepositions, auxiliaries, coordinators, complementisers, numerals,
|
|
19
|
+
// possessives and (sub/obj) pronouns procliticise rightward onto the following
|
|
20
|
+
// head; the possessive 's and verb particles encliticise leftward. A trailing
|
|
21
|
+
// proclitic with no head to its right attaches to the preceding group (so
|
|
22
|
+
// "…compare thee" keeps the object pronoun in the verb's group).
|
|
23
|
+
//
|
|
24
|
+
// Output is the shared IntonationalUnit[] shape, so display/scansion are unchanged.
|
|
25
|
+
// It reads only POS + canonicalRel + surface order; it never mutates the parse.
|
|
26
|
+
import { computePhiDomains } from './bracketing.js';
|
|
27
|
+
// ─── punctuation → break kind ──────────────────────────────────────
|
|
28
|
+
const IU_PUNCT_TAGS = new Set(['.', '!', '?', ':', ';', '-LRB-', '-RRB-', '(', ')']);
|
|
29
|
+
const IU_PUNCT_WORDS = new Set(['.', '!', '?', '…', ':', ';', '(', ')']);
|
|
30
|
+
function breakKind(w) {
|
|
31
|
+
if (IU_PUNCT_TAGS.has(w.lexicalClass) || IU_PUNCT_WORDS.has(w.word))
|
|
32
|
+
return 'iu';
|
|
33
|
+
if (w.lexicalClass === ',' || w.word === ',')
|
|
34
|
+
return 'phi';
|
|
35
|
+
return null; // other punctuation (quotes, etc.) — transparent to phrasing
|
|
36
|
+
}
|
|
37
|
+
function isAnyPunct(w) {
|
|
38
|
+
return /^[^A-Za-z0-9]+$/.test(w.lexicalClass) ||
|
|
39
|
+
w.lexicalClass === '-LRB-' || w.lexicalClass === '-RRB-';
|
|
40
|
+
}
|
|
41
|
+
// ─── κ: directional cliticisation ──────────────────────────────────
|
|
42
|
+
const PROCLITIC_REL = new Set([
|
|
43
|
+
'DET', 'CASE', 'AUX', 'AUXPASS', 'CC', 'COMPMARK', 'ADVMARK', 'NUMMOD', 'EXPL',
|
|
44
|
+
]);
|
|
45
|
+
const PROCLITIC_POS = /^(DT|PDT|IN|TO|CC|MD|WDT|WP|WP\$|EX|PRP\$|PRP)$/;
|
|
46
|
+
const OBJECT_REL = new Set(['DOBJ', 'IOBJ', 'OBL', 'OBJ']);
|
|
47
|
+
/** A clitic that leans LEFTWARD onto the preceding head (possessive 's, particle,
|
|
48
|
+
* OBJECT pronoun). An object pronoun encliticises to its verb ("compare thee",
|
|
49
|
+
* "give me") — so it must NOT be pulled rightward into the next phrase, which is
|
|
50
|
+
* what buried the preposition in "…compare thee | to a summer's day". */
|
|
51
|
+
function isEnclitic(w) {
|
|
52
|
+
if (w.lexicalClass === 'POS' || w.lexicalClass === 'RP' || w.canonicalRel === 'VPRT')
|
|
53
|
+
return true;
|
|
54
|
+
if (w.lexicalClass === 'PRP' && OBJECT_REL.has(w.canonicalRel ?? ''))
|
|
55
|
+
return true;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
/** A function word that leans RIGHTWARD onto the following content head. */
|
|
59
|
+
function isProclitic(w) {
|
|
60
|
+
if (w.isContent)
|
|
61
|
+
return false; // a promoted particle/demonstrative is a head
|
|
62
|
+
if (isEnclitic(w))
|
|
63
|
+
return false;
|
|
64
|
+
if (PROCLITIC_REL.has(w.canonicalRel ?? ''))
|
|
65
|
+
return true;
|
|
66
|
+
return PROCLITIC_POS.test(w.lexicalClass);
|
|
67
|
+
}
|
|
68
|
+
/** Build clitic groups over one IU segment's content/function words (no punct). */
|
|
69
|
+
function buildCliticGroups(words) {
|
|
70
|
+
const groups = [];
|
|
71
|
+
let pending = []; // proclitics awaiting their head
|
|
72
|
+
for (const w of words) {
|
|
73
|
+
if (isEnclitic(w) && groups.length > 0 && pending.length === 0) {
|
|
74
|
+
groups[groups.length - 1].tokens.push(w);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (isProclitic(w)) {
|
|
78
|
+
pending.push(w);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
// content head (or any non-clitic): open a CP with its pending proclitics.
|
|
82
|
+
groups.push({ tokens: [...pending, w] });
|
|
83
|
+
pending = [];
|
|
84
|
+
}
|
|
85
|
+
if (pending.length) {
|
|
86
|
+
if (groups.length)
|
|
87
|
+
groups[groups.length - 1].tokens.push(...pending);
|
|
88
|
+
else
|
|
89
|
+
groups.push({ tokens: pending });
|
|
90
|
+
}
|
|
91
|
+
return groups;
|
|
92
|
+
}
|
|
93
|
+
// ─── ϕ: phrase grouping (by dependency ϕ-domain) ───────────────────
|
|
94
|
+
// A ϕ boundary opens between two clitic groups when they fall in DIFFERENT
|
|
95
|
+
// ϕ-domains of the dependency tree (computePhiDomains, bracketing.ts) — the
|
|
96
|
+
// SAME constituent structure the cyclic stress rules use — replacing the old
|
|
97
|
+
// POS-keyed opensPhrase heuristic. So a stranded particle no longer opens a
|
|
98
|
+
// spurious oblique ϕ ("thought of" stays together), a branching object NP gets
|
|
99
|
+
// its own ϕ (reading | the latest biography), and a clause does not flatten
|
|
100
|
+
// when its head is mis-tagged (the relations, not the POS, decide).
|
|
101
|
+
function rightmostContent(cg) {
|
|
102
|
+
for (let i = cg.tokens.length - 1; i >= 0; i--)
|
|
103
|
+
if (cg.tokens[i].isContent)
|
|
104
|
+
return cg.tokens[i];
|
|
105
|
+
return cg.tokens[cg.tokens.length - 1];
|
|
106
|
+
}
|
|
107
|
+
/** The ϕ-domain id a clitic group sits in: the domain of its head (rightmost
|
|
108
|
+
* content word, else last token); a function-only group falls back to any of
|
|
109
|
+
* its tokens' domains (its proclitics share the domain of the head they lean
|
|
110
|
+
* onto). A new ϕ opens whenever this id changes between adjacent groups. */
|
|
111
|
+
function domainOf(cg, dom) {
|
|
112
|
+
const head = rightmostContent(cg) ?? cg.tokens[cg.tokens.length - 1];
|
|
113
|
+
const d = dom.get(head);
|
|
114
|
+
if (d !== undefined)
|
|
115
|
+
return d;
|
|
116
|
+
for (const t of cg.tokens) {
|
|
117
|
+
const dd = dom.get(t);
|
|
118
|
+
if (dd !== undefined)
|
|
119
|
+
return dd;
|
|
120
|
+
}
|
|
121
|
+
return -1;
|
|
122
|
+
}
|
|
123
|
+
/** Two PARSE-ROBUST ϕ-boundary markers from McAleese's Table-1 that the
|
|
124
|
+
* dependency-domain core cannot see when en-parse mis-attaches:
|
|
125
|
+
*
|
|
126
|
+
* • a COORDINATOR (CC "and / or / but") — each coordinate conjunct is its own
|
|
127
|
+
* ϕ; en-parse often flattens "old and gray and full" into a list of AMODs,
|
|
128
|
+
* so the conj relation is gone, but the CC token survives reliably.
|
|
129
|
+
* • a RELATIVE PRONOUN (WDT/WP "that / which / who") — it opens the relative
|
|
130
|
+
* clause's ϕ; en-parse routinely fails to build the ACL ("…the cat that
|
|
131
|
+
* caught the rat" flattened into one clause), but the relativiser is tagged.
|
|
132
|
+
*
|
|
133
|
+
* These are the two Table-1 triggers that survive attachment errors, so they
|
|
134
|
+
* supplement the dependency domains rather than re-introducing POS guesswork. */
|
|
135
|
+
function startsCoordOrRelative(cg) {
|
|
136
|
+
const t = cg.tokens[0];
|
|
137
|
+
if (!t)
|
|
138
|
+
return false;
|
|
139
|
+
if (t.lexicalClass === 'CC' || t.canonicalRel === 'CC')
|
|
140
|
+
return true;
|
|
141
|
+
return /^(WDT|WP|WP\$)$/.test(t.lexicalClass);
|
|
142
|
+
}
|
|
143
|
+
// A φ needs a stress-bearing ANCHOR to stand on its own. A content word is the
|
|
144
|
+
// usual one, but the 'n'-tier function words — demonstratives, quantifiers, and
|
|
145
|
+
// wh-words (relstress.functionLevel → 'n') — also carry a real beat, so a phrase
|
|
146
|
+
// built around one ("for THAT", "to EACH", "by WHICH") is a genuine φ with a
|
|
147
|
+
// nuclear and must NOT be dissolved into a neighbour the way a pure article /
|
|
148
|
+
// preposition / pronoun run ("around it") is. (Lemma/POS list mirrors relstress'
|
|
149
|
+
// 'n' category; kept local so the hierarchy layer does not depend on the stress one.)
|
|
150
|
+
const ANCHOR_LEMMAS = new Set([
|
|
151
|
+
'this', 'that', 'these', 'those',
|
|
152
|
+
'all', 'both', 'each', 'every', 'some', 'any', 'many', 'much', 'few', 'most',
|
|
153
|
+
'half', 'several', 'either', 'neither', 'enough', 'none',
|
|
154
|
+
]);
|
|
155
|
+
const ANCHOR_POS = /^(PDT|WDT|WP|WP\$|WRB)$/;
|
|
156
|
+
function canAnchorBeat(pp) {
|
|
157
|
+
return pp.cliticGroups.some(cg => cg.tokens.some(t => t.isContent ||
|
|
158
|
+
/^VB/.test(t.lexicalClass) || // a verb group ("has been") is a real ϕ even
|
|
159
|
+
// when its tokens are non-content auxiliaries —
|
|
160
|
+
// it must not fold back into the subject NP
|
|
161
|
+
ANCHOR_LEMMAS.has(t.word.toLowerCase().replace(/['’]/g, '')) ||
|
|
162
|
+
ANCHOR_POS.test(t.lexicalClass)));
|
|
163
|
+
}
|
|
164
|
+
function groupIntoPhrases(cgs, commaBeforeCG, dom) {
|
|
165
|
+
const phrases = [];
|
|
166
|
+
let current = [];
|
|
167
|
+
let prev = null;
|
|
168
|
+
let currentCommaPreceded = false;
|
|
169
|
+
for (const cg of cgs) {
|
|
170
|
+
const brk = current.length > 0 && prev !== null &&
|
|
171
|
+
(commaBeforeCG.has(cg) || startsCoordOrRelative(cg) ||
|
|
172
|
+
domainOf(cg, dom) !== domainOf(prev, dom));
|
|
173
|
+
if (brk) {
|
|
174
|
+
phrases.push({ cgs: current, commaPreceded: currentCommaPreceded });
|
|
175
|
+
current = [];
|
|
176
|
+
currentCommaPreceded = commaBeforeCG.has(cg);
|
|
177
|
+
}
|
|
178
|
+
current.push(cg);
|
|
179
|
+
prev = cg;
|
|
180
|
+
}
|
|
181
|
+
if (current.length)
|
|
182
|
+
phrases.push({ cgs: current, commaPreceded: currentCommaPreceded });
|
|
183
|
+
// A ϕ must have a beat-anchor: a phrase of only un-anchored function words (a
|
|
184
|
+
// stranded preposition + pronoun like "around it", an orphan determiner) has no
|
|
185
|
+
// nuclear to carry a beat, so it MERGES into its neighbour — into the previous
|
|
186
|
+
// phrase when there is one (it leans back onto the head it modifies), else the
|
|
187
|
+
// next. A phrase anchored by a demonstrative/quantifier/wh ("for THAT") is NOT
|
|
188
|
+
// merged — it is a genuine φ.
|
|
189
|
+
//
|
|
190
|
+
// BUT: a phrase preceded by a COMMA is NEVER merged, even if it lacks a
|
|
191
|
+
// beat-anchor. A comma is an OVERT prosodic boundary the poet placed; merging
|
|
192
|
+
// across it destroys the boundary and flattens the post-comma material into the
|
|
193
|
+
// pre-comma phrase ("among them" after "And of the best," → xww instead of xnw).
|
|
194
|
+
// A function-word-only post-comma phrase keeps its separate ϕ so the
|
|
195
|
+
// relativiser can apply the phrase-initial beat and the givenness escape.
|
|
196
|
+
const merged = [];
|
|
197
|
+
for (const p of phrases) {
|
|
198
|
+
const pp = { cliticGroups: p.cgs };
|
|
199
|
+
if (!canAnchorBeat(pp) && merged.length > 0 && !p.commaPreceded) {
|
|
200
|
+
merged[merged.length - 1].cliticGroups.push(...p.cgs);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
merged.push(pp);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// A leading un-anchored phrase folds forward into the next — but NOT if it was
|
|
207
|
+
// comma-preceded (a comma before the first phrase would be line-initial, which
|
|
208
|
+
// doesn't happen; this guard is for safety).
|
|
209
|
+
if (merged.length >= 2 && !canAnchorBeat(merged[0]) && !phrases[0].commaPreceded) {
|
|
210
|
+
merged[1].cliticGroups.unshift(...merged[0].cliticGroups);
|
|
211
|
+
merged.shift();
|
|
212
|
+
}
|
|
213
|
+
return merged;
|
|
214
|
+
}
|
|
215
|
+
// ─── top level ─────────────────────────────────────────────────────
|
|
216
|
+
export function buildProsodicHierarchy(sent) {
|
|
217
|
+
// ϕ-domains over the dependency tree (the same constituent structure the
|
|
218
|
+
// cyclic stress rules use) — the grouping signal for phonological phrases.
|
|
219
|
+
const dom = computePhiDomains(sent);
|
|
220
|
+
const ius = [];
|
|
221
|
+
let segWords = [];
|
|
222
|
+
let commaAfterPos = new Set(); // positions in segWords with a comma after
|
|
223
|
+
const flush = () => {
|
|
224
|
+
if (segWords.length === 0) {
|
|
225
|
+
commaAfterPos = new Set();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// A φ-break (comma) is a HARD boundary for clitic-group formation: a proclitic
|
|
229
|
+
// must not lean across a comma onto a head in the next phrase. (Letting it do
|
|
230
|
+
// so silently glued "for that ," onto the following "a specialized branch" — both
|
|
231
|
+
// "for" and "that" procliticise rightward onto "specialized" — so the comma fell
|
|
232
|
+
// INSIDE one clitic group and the φ-break was lost.) So we split the IU segment
|
|
233
|
+
// into RUNS at the comma positions, build clitic groups WITHIN each run, and mark
|
|
234
|
+
// the first CG of every run after the first as φ-preceded.
|
|
235
|
+
const runs = [];
|
|
236
|
+
let run = [];
|
|
237
|
+
segWords.forEach((w, i) => {
|
|
238
|
+
run.push(w);
|
|
239
|
+
if (commaAfterPos.has(i)) {
|
|
240
|
+
runs.push(run);
|
|
241
|
+
run = [];
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
if (run.length)
|
|
245
|
+
runs.push(run);
|
|
246
|
+
const cgs = [];
|
|
247
|
+
const commaBeforeCG = new Set();
|
|
248
|
+
runs.forEach((r, ri) => {
|
|
249
|
+
const rcgs = buildCliticGroups(r);
|
|
250
|
+
if (ri > 0 && rcgs.length > 0)
|
|
251
|
+
commaBeforeCG.add(rcgs[0]);
|
|
252
|
+
cgs.push(...rcgs);
|
|
253
|
+
});
|
|
254
|
+
ius.push({ phonologicalPhrases: groupIntoPhrases(cgs, commaBeforeCG, dom) });
|
|
255
|
+
segWords = [];
|
|
256
|
+
commaAfterPos = new Set();
|
|
257
|
+
};
|
|
258
|
+
for (const w of sent.words) {
|
|
259
|
+
const kind = breakKind(w);
|
|
260
|
+
if (kind === 'iu') {
|
|
261
|
+
flush();
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (kind === 'phi') {
|
|
265
|
+
if (segWords.length)
|
|
266
|
+
commaAfterPos.add(segWords.length - 1);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (isAnyPunct(w))
|
|
270
|
+
continue; // transparent punctuation
|
|
271
|
+
segWords.push(w);
|
|
272
|
+
}
|
|
273
|
+
flush();
|
|
274
|
+
return ius;
|
|
275
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relstress.d.ts","sourceRoot":"","sources":["../../src/calliope/relstress.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAyB,MAAM,aAAa,CAAC;AAmkB/E,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAkCrF"}
|