add support for word end and phoneme deletion
This commit is contained in:
parent
a19102f82e
commit
07be982b51
3 changed files with 63 additions and 16 deletions
|
@ -5,15 +5,15 @@ export type initAction = {
|
||||||
type: "INIT"
|
type: "INIT"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initState = (changesArgument: number = -1): stateType => {
|
export const initState = (changesArgument: number): stateType => {
|
||||||
const state = {
|
const state = {
|
||||||
epochs: [
|
epochs: [
|
||||||
{
|
{
|
||||||
name: 'epoch 1',
|
name: 'epoch 1',
|
||||||
changes: [
|
changes: [
|
||||||
'[+ occlusive - nasal]>[+ occlusive + nasal]/n_.',
|
'[+ occlusive - nasal]>[+ occlusive + nasal]/n_.',
|
||||||
// 'at>ta/._#',
|
'a>ɯ/._#',
|
||||||
// '[+ sonorant - low rounded high back]>0/._.',
|
'[+ sonorant - low rounded high back]>0/._.',
|
||||||
// 'nn>nun/._.',
|
// 'nn>nun/._.',
|
||||||
// '[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_.',
|
// '[+ nasal][+ obstruent]>[+ nasal obstruent aspirated ]/#_.',
|
||||||
// '[+ sonorant rounded]>[+ sonorant - rounded]/._#'
|
// '[+ sonorant rounded]>[+ sonorant - rounded]/._#'
|
||||||
|
@ -43,7 +43,7 @@ export const initState = (changesArgument: number = -1): stateType => {
|
||||||
},
|
},
|
||||||
t: {
|
t: {
|
||||||
grapheme: 't', features: {
|
grapheme: 't', features: {
|
||||||
occlusive: true, coronal: true, obstruent: true
|
occlusive: true, coronal: true, obstruent: true, nasal: false
|
||||||
},
|
},
|
||||||
ʰ: {
|
ʰ: {
|
||||||
grapheme: 'tʰ', features: {
|
grapheme: 'tʰ', features: {
|
||||||
|
@ -86,7 +86,7 @@ export const initState = (changesArgument: number = -1): stateType => {
|
||||||
{lexeme: 'ənta', epoch: state.epochs[0]}
|
{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;
|
return state;
|
||||||
}
|
}
|
|
@ -43,6 +43,7 @@ const findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {
|
||||||
})
|
})
|
||||||
return featureBundle;
|
return featureBundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {
|
const findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {
|
||||||
let featureBundle = []
|
let featureBundle = []
|
||||||
let lastIndex = lexeme.length - 1;
|
let lastIndex = lexeme.length - 1;
|
||||||
|
@ -94,6 +95,8 @@ const mapToPositiveAndNegativeFeatures = phoneme => (
|
||||||
const mapStringToFeatures = (ruleString, phones) => {
|
const mapStringToFeatures = (ruleString, phones) => {
|
||||||
if (ruleString) {
|
if (ruleString) {
|
||||||
if (ruleString === '.') return [];
|
if (ruleString === '.') return [];
|
||||||
|
if (ruleString === '#') return ['#']
|
||||||
|
if (ruleString === '0') return [];
|
||||||
const ruleBrackets = ruleString.match(/\[.*\]/)
|
const ruleBrackets = ruleString.match(/\[.*\]/)
|
||||||
if (ruleBrackets) {
|
if (ruleBrackets) {
|
||||||
return ruleString
|
return ruleString
|
||||||
|
@ -129,6 +132,7 @@ const isPhonemeBoundByRule = phonemeFeatures => (ruleFeature, index) => {
|
||||||
const phoneme = phonemeFeatures[index].features;
|
const phoneme = phonemeFeatures[index].features;
|
||||||
return Object.entries(ruleFeature).reduce((bool, [feature, value]) => {
|
return Object.entries(ruleFeature).reduce((bool, [feature, value]) => {
|
||||||
if (!bool) return false;
|
if (!bool) return false;
|
||||||
|
if (!phoneme.hasOwnProperty(feature)) return false;
|
||||||
if (!phoneme[feature] && !value) return true;
|
if (!phoneme[feature] && !value) return true;
|
||||||
if (phoneme[feature] !== value) return false;
|
if (phoneme[feature] !== value) return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -141,9 +145,8 @@ const isEnvironmentBoundByRule = (phonemeFeatures, ruleFeatures) => {
|
||||||
? true : false;
|
? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const swapPhoneme = (phoneme, newFeatures, features) => {
|
const swapPhoneme = (phoneme, newFeatures, features) => {
|
||||||
|
if (!newFeatures) return {}
|
||||||
const newPhonemeFeatures = Object.entries(newFeatures)
|
const newPhonemeFeatures = Object.entries(newFeatures)
|
||||||
.reduce((newPhoneme, [newFeature, newValue]) => ({ ...newPhoneme, [newFeature]: newValue })
|
.reduce((newPhoneme, [newFeature, newValue]) => ({ ...newPhoneme, [newFeature]: newValue })
|
||||||
, {...phoneme.features});
|
, {...phoneme.features});
|
||||||
|
@ -154,12 +157,30 @@ const swapPhoneme = (phoneme, newFeatures, features) => {
|
||||||
, newPhonemeCandidates[newPhonemeCandidates.length - 1])[0];
|
, 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) => {
|
export const transformLexeme = (lexemeBundle, rule, features) => {
|
||||||
const {pre, post, position} = rule.environment;
|
const {pre, post, position} = rule.environment;
|
||||||
const newLexeme = lexemeBundle.reduce((newLexeme, phoneme, index) => {
|
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 ( 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(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];
|
if (!isEnvironmentBoundByRule(lexemeBundle.slice(index, index + post.length), post)) return [...newLexeme, phoneme];
|
||||||
const newPhoneme = swapPhoneme(phoneme, rule.newFeatures[0], features);
|
const newPhoneme = swapPhoneme(phoneme, rule.newFeatures[0], features);
|
||||||
return [...newLexeme, newPhoneme];
|
return [...newLexeme, newPhoneme];
|
||||||
|
@ -173,7 +194,7 @@ const transformLexicon = lexiconBundle =>
|
||||||
ruleBundle =>
|
ruleBundle =>
|
||||||
features =>
|
features =>
|
||||||
lexiconBundle.map(lexemeBundle => ruleBundle.reduce(
|
lexiconBundle.map(lexemeBundle => ruleBundle.reduce(
|
||||||
(lexeme, rule) => transformLexeme(lexeme, rule, features)
|
(lexeme, rule, i) => transformLexeme(lexeme, rule, features)
|
||||||
, lexemeBundle
|
, lexemeBundle
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ describe('Results', () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
grapheme: 't',
|
grapheme: 't',
|
||||||
features: { occlusive: true, coronal: true, obstruent: true }
|
features: { occlusive: true, coronal: true, obstruent: true, nasal: false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
grapheme: 'a',
|
grapheme: 'a',
|
||||||
|
@ -88,7 +88,7 @@ describe('Results', () => {
|
||||||
|
|
||||||
it('results returned from first sound change rule', () => {
|
it('results returned from first sound change rule', () => {
|
||||||
const action = {type: 'RUN'};
|
const action = {type: 'RUN'};
|
||||||
state = initState(0)
|
state = initState(1)
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
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'};
|
const action = {type: 'RUN'};
|
||||||
state = initState()
|
state = initState(2)
|
||||||
console.log(stateReducer(state, action).results)
|
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch 1',
|
||||||
lexicon: [
|
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'
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// ]);
|
||||||
|
// });
|
||||||
|
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue