patch decomposeRules in results to process phoneme sequences

This commit is contained in:
Sorrel Bri 2020-02-13 23:40:34 -08:00
parent bcf79aa28c
commit 1b51405f02
3 changed files with 63 additions and 29 deletions

View file

@ -11,12 +11,12 @@ export const initState = (changesArgument: number = -1): stateType => {
{
name: 'epoch 1',
changes: [
'[+ occlusive - nasal]>[+ occlusive nasal]/n_',
'at>ta/_#',
'[+ sonorant - low rounded high back]>_/_',
'nn>nun/_',
'[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_',
'[+ sonorant rounded]>[+ sonorant - rounded]/_#'
'[+ occlusive - nasal]>[+ occlusive nasal]/n_.',
'at>ta/._#',
'[+ sonorant - low rounded high back]>0/._.',
'nn>nun/._.',
'[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_.',
'[+ sonorant rounded]>[+ sonorant - rounded]/._#'
]
}
],

View file

@ -16,6 +16,15 @@ export type decomposedRulesType = [
}
]
type ruleBundle = {
environment: {
pre: string,
position: string,
post: string
},
newFeatures: string
}
const findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {
let featureBundle = []
let lastIndex = lexeme.length - 1;
@ -54,10 +63,10 @@ const findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {
return featureBundle;
}
const decomposeRule = (rule: string) => {
let decomposedChange = rule.split('>');
decomposedChange = [decomposedChange[0], ...decomposedChange[1].split('/')]
decomposedChange = [decomposedChange[0], decomposedChange[1], ...decomposedChange[2].split('_')];
const decomposeRule = (rule: string): ruleBundle => {
// splits rule at '>' '/' and '_' substrings resulting in array of length 4
const decomposedChange = rule.split(/>|\/|_/g);
const ruleBundle = {
environment: {
pre: decomposedChange[2],
@ -71,16 +80,29 @@ const decomposeRule = (rule: string) => {
const mapStringToFeatures = (ruleString, phones) => {
if (ruleString) {
if (ruleString === '.') return [];
const ruleBrackets = ruleString.match(/\[.*\]/)
if (ruleBrackets) {
const ruleFeatures = ruleString.match(/(?!\[).*(?<!\])/)[0]
const plusIndex = ruleFeatures.indexOf('+');
const minusIndex = ruleFeatures.indexOf('-');
const positiveFeatures = ruleFeatures.slice(plusIndex + 1, minusIndex).trim().split(' ');
const positiveFeaturesMap = positiveFeatures.map(feature => ({[feature]: true}))
const negativeFeatures = ruleFeatures.slice(minusIndex +1).trim().split(' ');
const negativeFeaturesMap = negativeFeatures.map(feature => ({[feature]: false}))
return {...positiveFeaturesMap, ...negativeFeaturesMap}
const ruleFeatures = ruleString
.split('[')
// filter out empty strings
.filter(v => v)
.map((phoneme) => {
const positiveFeatures = phoneme.match(/(?=\+.).*(?<=\-)|(?=\+.).*(?!\-).*(?<=\])/g)
const positiveFeaturesMap = positiveFeatures ? positiveFeatures[0]
.trim().match(/\w+/g)
.reduce((map, feature) => ({...map, [feature]: true}), {})
: {}
const negativeFeatures = phoneme.match(/(?=\-.).*(?<=\+)|(?=\-.).*(?!\+).*(?<=\])/g)
const negativeFeaturesMap = negativeFeatures ? negativeFeatures[0]
.trim().match(/\w+/g)
.reduce((map, feature) => ({...map, [feature]: false}), {})
: {}
return {...positiveFeaturesMap, ...negativeFeaturesMap}
})
return ruleFeatures;
}
const grapheme = ruleString;
return findFeaturesFromGrapheme(phones, grapheme);
@ -89,17 +111,12 @@ const mapStringToFeatures = (ruleString, phones) => {
}
const mapRuleBundleToFeatureBundle = (ruleBundle, phones) => {
// ! for each object in ruleBundle, map values to array of objects with feature-boolean key-value pairs
// for each object in ruleBundle, map values to array of objects with feature-boolean key-value pairs
const featureBundle = {...ruleBundle};
console.log(featureBundle)
featureBundle.environment.pre = mapStringToFeatures(featureBundle.environment.pre, phones);
console.log(featureBundle.environment.pre)
featureBundle.environment.position = mapStringToFeatures(featureBundle.environment.position, phones);
console.log(featureBundle.environment.position)
featureBundle.environment.post = mapStringToFeatures(featureBundle.environment.post, phones);
console.log(featureBundle.environment.post)
featureBundle.newFeatures = mapStringToFeatures(featureBundle.newFeatures, phones);
console.log(featureBundle.newFeatures)
return featureBundle;
}
@ -111,10 +128,27 @@ export const decomposeRules = (epoch: epochType, phones: {[key: string]: phoneTy
}
export const run = (state: stateType, action: resultsAction): stateType => {
// ! one epoch only
// rule 0 '[+ occlusive - nasal]>[+ occlusive nasal]/n_'
// for each epoch
// TODO iterate through each epoch
let ruleBundle = state.epochs[0].changes;
ruleBundle = ruleBundle.map(rule => decomposeRule(rule))
// for each rule in epoch
ruleBundle = ruleBundle.map(rule => decomposeRule(rule))
// parse rule into feature bundles for
// environment
// pre-target
// post-target
// target
// mutation
// for each item in lexicon
// match targets in environments
// mutate target
// temporarily store lexical item
// store lexical items in resulting epoch
ruleBundle.map(rule => {
rule.forEach(position => {

View file

@ -31,10 +31,10 @@ describe('Results', () => {
],
post: [],
},
newFeatures: {occlusive: true, nasal: true}
newFeatures: [{occlusive: true, nasal: true}]
}
];
expect(decomposeRules(epoch, phones)).toBe(result);
expect(decomposeRules(epoch, phones)).toStrictEqual(result);
})
// it('results returned from first sound change rule', () => {