| |
| |
| |
| |
| |
| |
| 'use strict'; |
|
|
| function sentences(text) { |
| return text.replace(/\s+/g, ' ').split(/(?<=[.!?])\s+/).map(s => s.trim()).filter(Boolean); |
| } |
|
|
| |
| function leadSubject(s) { |
| const m = s.match(/^((?:The|A|An)\s+)?([A-Z][A-Za-z]+(?:\s+[A-Z][a-z]+)*)/); |
| return m ? (m[1] || '') + m[2] : (s.split(/\s+/).slice(0, 2).join(' ')); |
| } |
|
|
| function decompose(sentence) { |
| const out = []; |
| let s = sentence.replace(/\s+/g, ' ').trim(); |
| const subj = leadSubject(s); |
|
|
| |
| const appo = s.match(/^(.+?),\s+(a|an|the)\s+([^,]+?),\s+(.*)$/i); |
| if (appo && /^[A-Z]/.test(appo[1].trim()) && appo[1].split(/\s+/).length <= 4) { |
| out.push(`${appo[1].trim()} is ${appo[2]} ${appo[3].trim()}.`); |
| s = `${appo[1].trim()} ${appo[4].trim()}`; |
| } |
|
|
| |
| |
| const rel = s.match(/^(.*?\b([A-Z][A-Za-z]+(?:\s+[A-Z][a-z]+)*|\w+))\s*,?\s+(who|which|that)\s+(.+)$/); |
| if (rel) { |
| const head = s.slice(0, rel[1].length).trim().replace(/,$/, ''); |
| const antecedent = rel[2]; |
| let tail = rel[4].trim(); |
| |
| const tailCut = tail.match(/^(.+?)(?:,\s+(?:and\s+)?(.*))?$/); |
| out.push(`${cap(antecedent)} ${tailCut[1].trim()}`.replace(/\.*$/, '.')); |
| s = head + (tailCut && tailCut[2] ? ' ' + tailCut[2] : ''); |
| } |
|
|
| |
| |
| const conj = s.match(/^(.+?)\s+and\s+(.+)$/); |
| if (conj && !/^[A-Z]/.test(conj[2].trim()) && /^(is|are|was|were|has|have|treats?|requires?|produces?|makes?|forbids?|bans?|owns?|can|may)\b/i.test(conj[2].trim())) { |
| out.push(clean(conj[1])); |
| out.push(clean(`${subj} ${conj[2]}`)); |
| } else { |
| out.push(clean(s)); |
| } |
| return out.map(f => f.replace(/\s+/g, ' ').trim()).filter(f => f.split(/\s+/).length >= 3); |
| } |
|
|
| function cap(w) { return w.charAt(0).toUpperCase() + w.slice(1); } |
| function clean(s) { s = s.trim().replace(/\s+/g, ' '); if (!/[.!?]$/.test(s)) s += '.'; return s; } |
|
|
| function ingest(text) { |
| const facts = []; |
| for (const sent of sentences(text)) for (const f of decompose(sent)) if (!facts.includes(f)) facts.push(f); |
| return facts; |
| } |
|
|
| module.exports = { ingest, decompose, sentences }; |
|
|