add support for word end and phoneme deletion

This commit is contained in:
Sorrel Bri 2020-02-19 18:33:00 -08:00
parent a19102f82e
commit 07be982b51
3 changed files with 63 additions and 16 deletions

View file

@ -5,15 +5,15 @@ export type initAction = {
type: "INIT"
}
export const initState = (changesArgument: number = -1): stateType => {
export const initState = (changesArgument: number): stateType => {
const state = {
epochs: [
{
name: 'epoch 1',
changes: [
'[+ occlusive - nasal]>[+ occlusive + nasal]/n_.',
// 'at>ta/._#',
// '[+ sonorant - low rounded high back]>0/._.',
'a>ɯ/._#',
'[+ sonorant - low rounded high back]>0/._.',
// 'nn>nun/._.',
// '[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_.',
// '[+ sonorant rounded]>[+ sonorant - rounded]/._#'
@ -43,7 +43,7 @@ export const initState = (changesArgument: number = -1): stateType => {
},
t: {
grapheme: 't', features: {
occlusive: true, coronal: true, obstruent: true
occlusive: true, coronal: true, obstruent: true, nasal: false
},
ʰ: {
grapheme: 'tʰ', features: {
@ -86,7 +86,7 @@ export const initState = (changesArgument: number = -1): stateType => {
{lexeme: 'ənta', epoch: state.epochs[0]}
]
if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(changesArgument, 1)
if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(0, changesArgument)
return state;
}

View file

@ -43,6 +43,7 @@ const findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {
})
return featureBundle;
}
const findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {
let featureBundle = []
let lastIndex = lexeme.length - 1;
@ -94,6 +95,8 @@ const mapToPositiveAndNegativeFeatures = phoneme => (
const mapStringToFeatures = (ruleString, phones) => {
if (ruleString) {
if (ruleString === '.') return [];
if (ruleString === '#') return ['#']
if (ruleString === '0') return [];
const ruleBrackets = ruleString.match(/\[.*\]/)
if (ruleBrackets) {
return ruleString
@ -129,6 +132,7 @@ const isPhonemeBoundByRule = phonemeFeatures => (ruleFeature, index) => {
const phoneme = phonemeFeatures[index].features;
return Object.entries(ruleFeature).reduce((bool, [feature, value]) => {
if (!bool) return false;
if (!phoneme.hasOwnProperty(feature)) return false;
if (!phoneme[feature] && !value) return true;
if (phoneme[feature] !== value) return false;
return true;
@ -141,9 +145,8 @@ const isEnvironmentBoundByRule = (phonemeFeatures, ruleFeatures) => {
? true : false;
}
const swapPhoneme = (phoneme, newFeatures, features) => {
if (!newFeatures) return {}
const newPhonemeFeatures = Object.entries(newFeatures)
.reduce((newPhoneme, [newFeature, newValue]) => ({ ...newPhoneme, [newFeature]: newValue })
, {...phoneme.features});
@ -154,12 +157,30 @@ const swapPhoneme = (phoneme, newFeatures, features) => {
, newPhonemeCandidates[newPhonemeCandidates.length - 1])[0];
}
const transformLexemeInitial = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {
if (index !== pre.length - 1) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule(lexemeBundle.slice(index, index + post.length), post)) return [...newLexeme, phoneme];
const newPhoneme = swapPhoneme(phoneme, newFeatures[0], features);
return [...newLexeme, newPhoneme];
}
const transformLexemeCoda = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {
if (index + post.length !== lexemeBundle.length) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];
const newPhoneme = swapPhoneme(phoneme, newFeatures[0], features);
return [...newLexeme, newPhoneme];
}
export const transformLexeme = (lexemeBundle, rule, features) => {
const {pre, post, position} = rule.environment;
const newLexeme = lexemeBundle.reduce((newLexeme, phoneme, index) => {
if (pre.find(val => val === '#')) return transformLexemeInitial(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);
if (post.find(val => val === '#')) return transformLexemeCoda(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);
if ( index < pre.length || index >= lexemeBundle.length - post.length ) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule([phoneme], rule.environment.position)) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];
if (!isEnvironmentBoundByRule(lexemeBundle.slice(index, index + post.length), post)) return [...newLexeme, phoneme];
const newPhoneme = swapPhoneme(phoneme, rule.newFeatures[0], features);
return [...newLexeme, newPhoneme];
@ -173,7 +194,7 @@ const transformLexicon = lexiconBundle =>
ruleBundle =>
features =>
lexiconBundle.map(lexemeBundle => ruleBundle.reduce(
(lexeme, rule) => transformLexeme(lexeme, rule, features)
(lexeme, rule, i) => transformLexeme(lexeme, rule, features)
, lexemeBundle
))

View file

@ -55,7 +55,7 @@ describe('Results', () => {
},
{
grapheme: 't',
features: { occlusive: true, coronal: true, obstruent: true }
features: { occlusive: true, coronal: true, obstruent: true, nasal: false }
},
{
grapheme: 'a',
@ -88,7 +88,7 @@ describe('Results', () => {
it('results returned from first sound change rule', () => {
const action = {type: 'RUN'};
state = initState(0)
state = initState(1)
expect(stateReducer(state, action).results).toEqual([
{
pass: 'epoch 1',
@ -99,18 +99,44 @@ describe('Results', () => {
]);
});
if('results returned from sound change suite', () => {
it('results returned through second sound change rule', () => {
const action = {type: 'RUN'};
state = initState()
console.log(stateReducer(state, action).results)
state = initState(2)
expect(stateReducer(state, action).results).toEqual([
{
pass: 'epoch 1',
lexicon: [
'anna', 'anat', 'anət', 'anna', 'tan', 'ənna'
'annɯ', 'anat', 'anət', 'annɯ', 'tan', 'ənnɯ'
]
}
]);
});
});
it('results returned through third sound change rule', () => {
const action = {type: 'RUN'};
state = initState(3)
expect(stateReducer(state, action).results).toEqual([
{
pass: 'epoch 1',
lexicon: [
'annɯ', 'anat', 'ant', 'annɯ', 'tan', 'nnɯ'
]
}
]);
});
// if('results returned from sound change suite', () => {
// const action = {type: 'RUN'};
// state = initState()
// console.log(stateReducer(state, action).results)
// expect(stateReducer(state, action).results).toEqual([
// {
// pass: 'epoch 1',
// lexicon: [
// 'anna', 'anta', 'anət', 'anna', 'tan', 'ənna'
// ]
// }
// ]);
// });
});