test green for run from parsed epoch latl
This commit is contained in:
parent
35f815a9c9
commit
49419a39ee
7 changed files with 65 additions and 47 deletions
|
@ -5,7 +5,7 @@ describe('Epochs', () => {
|
||||||
beforeEach(()=> {
|
beforeEach(()=> {
|
||||||
state.epochs = [
|
state.epochs = [
|
||||||
{
|
{
|
||||||
name: 'epoch 1',
|
name: 'epoch-1',
|
||||||
changes: [''],
|
changes: [''],
|
||||||
parent: null
|
parent: null
|
||||||
}
|
}
|
||||||
|
@ -18,45 +18,45 @@ describe('Epochs', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('epochs addition returns new epochs list', () => {
|
it('epochs addition returns new epochs list', () => {
|
||||||
const action = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: [''], parent: null}};
|
const action = {type: 'ADD_EPOCH', value: { name: 'epoch-2', changes: [''], parent: null}};
|
||||||
expect(stateReducer(state, action)).toEqual({...state, epochs: [...state.epochs, action.value]})
|
expect(stateReducer(state, action)).toEqual({...state, epochs: [...state.epochs, action.value]})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('epoch name mutation returns new epochs list with mutation', () => {
|
it('epoch-name mutation returns new epochs list with mutation', () => {
|
||||||
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: ['']}};
|
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch-2', changes: ['']}};
|
||||||
const secondAction = {type: 'SET_EPOCH', value: { index: 0, name: 'proto-lang'}};
|
const secondAction = {type: 'SET_EPOCH', value: { index: 0, name: 'proto-lang'}};
|
||||||
const secondState = stateReducer(state, firstAction);
|
const secondState = stateReducer(state, firstAction);
|
||||||
expect(stateReducer(secondState, secondAction)).toEqual(
|
expect(stateReducer(secondState, secondAction)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
epochs: [
|
epochs: [
|
||||||
{name: 'proto-lang', changes: [''], parent: null},
|
{name: 'proto-lang', changes: [''], parent: null},
|
||||||
{name: 'epoch 2', changes: [''], parent: null}
|
{name: 'epoch-2', changes: [''], parent: null}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('epoch changes mutation returns new epochs list with mutation', () => {
|
it('epoch changes mutation returns new epochs list with mutation', () => {
|
||||||
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: ['']}};
|
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch-2', changes: ['']}};
|
||||||
const secondAction = {type: 'SET_EPOCH', value: { index: 0, changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n']}};
|
const secondAction = {type: 'SET_EPOCH', value: { index: 0, changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n']}};
|
||||||
const secondState = stateReducer(state, firstAction);
|
const secondState = stateReducer(state, firstAction);
|
||||||
expect(stateReducer(secondState, secondAction)).toEqual(
|
expect(stateReducer(secondState, secondAction)).toEqual(
|
||||||
{...state,
|
{...state,
|
||||||
epochs: [
|
epochs: [
|
||||||
{name: 'epoch 1', changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n'], parent: null},
|
{name: 'epoch-1', changes: ['n>t/_#', '[+plosive]>[+nasal -plosive]/_n'], parent: null},
|
||||||
{name: 'epoch 2', changes: [''], parent: null}
|
{name: 'epoch-2', changes: [''], parent: null}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('epochs returned with deleted epoch removed', () => {
|
it('epochs returned with deleted epoch removed', () => {
|
||||||
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch 2', changes: ['']}};
|
const firstAction = {type: 'ADD_EPOCH', value: { name: 'epoch-2', changes: ['']}};
|
||||||
const stateWithTwoEpochs = stateReducer(state, firstAction);
|
const stateWithTwoEpochs = stateReducer(state, firstAction);
|
||||||
const secondAction = {type: 'REMOVE_EPOCH', value: {index: 0, name: 'epoch 1'}}
|
const secondAction = {type: 'REMOVE_EPOCH', value: {index: 0, name: 'epoch-1'}}
|
||||||
expect(stateReducer(stateWithTwoEpochs, secondAction)).toEqual({
|
expect(stateReducer(stateWithTwoEpochs, secondAction)).toEqual({
|
||||||
...state,
|
...state,
|
||||||
epochs: [{ name: 'epoch 2', changes: [''], parent: null}]
|
epochs: [{ name: 'epoch-2', changes: [''], parent: null}]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ 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_.',
|
||||||
'a>ɯ/._#',
|
'a>ɯ/._#',
|
||||||
|
|
|
@ -90,6 +90,9 @@ const parseReferent = (tree, token, index, tokens) => {
|
||||||
tree[tree.length - 1] = {...lastNode, name: token.value, type: 'epoch' }
|
tree[tree.length - 1] = {...lastNode, name: token.value, type: 'epoch' }
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
case 'epoch': {
|
||||||
|
return [...tree, { type: 'rule', value: token.value } ]
|
||||||
|
}
|
||||||
case 'rule': {
|
case 'rule': {
|
||||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value }
|
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value }
|
||||||
return tree;
|
return tree;
|
||||||
|
@ -264,17 +267,14 @@ export const buildTree = tokens => {
|
||||||
|
|
||||||
export const generateAST = latl => {
|
export const generateAST = latl => {
|
||||||
// tokenize
|
// tokenize
|
||||||
const tokens = tokenize(latl);
|
const tokens = tokenize(latl.trim());
|
||||||
|
|
||||||
// build tree
|
// build tree
|
||||||
const tree = buildTree(tokens);
|
const tree = buildTree(tokens);
|
||||||
|
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const parseLatl = (state, action) => {
|
export const parseLatl = (state, action) => {
|
||||||
const latl = state.latl;
|
const latl = state.latl;
|
||||||
console.log(latl)
|
|
||||||
const AST = generateAST(latl);
|
const AST = generateAST(latl);
|
||||||
Object.entries(AST).forEach(([key, value]) => state[key] = value);
|
Object.entries(AST).forEach(([key, value]) => state[key] = value);
|
||||||
return { ...state }
|
return { ...state }
|
||||||
|
@ -295,7 +295,7 @@ const tokenTypes = [
|
||||||
['slash', `\/`],
|
['slash', `\/`],
|
||||||
['dot', `\\.`],
|
['dot', `\\.`],
|
||||||
['underscore', `\\_`],
|
['underscore', `\\_`],
|
||||||
[`referent`, `[A-Za-z]+`],
|
[`referent`, `[A-Za-z]+[\\w\\-\\_]*`],
|
||||||
['equal', `=`],
|
['equal', `=`],
|
||||||
[`lineBreak`, `\\n`]
|
[`lineBreak`, `\\n`]
|
||||||
// [`whiteSpace`, `\\s+`]
|
// [`whiteSpace`, `\\s+`]
|
||||||
|
|
|
@ -45,25 +45,40 @@ describe('LATL', () => {
|
||||||
const state = initState();
|
const state = initState();
|
||||||
const setAction = {
|
const setAction = {
|
||||||
type: 'SET_LATL',
|
type: 'SET_LATL',
|
||||||
value: epochDefinitionLatl
|
value: runEpochLatl
|
||||||
}
|
}
|
||||||
const latlState = stateReducer(state, setAction);
|
const latlState = stateReducer(state, setAction);
|
||||||
const parseState = parseLatl(latlState, {})
|
const parseState = parseLatl(latlState, {})
|
||||||
expect(parseState).toStrictEqual(epochState);
|
// expect(parseState).toStrictEqual(epochState);
|
||||||
parseState.lexicon[0].epoch = 'PROTO'
|
parseState.lexicon[0].epoch = 'PROTO'
|
||||||
const runState = stateReducer(parseState, {type: 'RUN', value:{}})
|
const runState = stateReducer(parseState, {type: 'RUN', value:{}})
|
||||||
console.log(runState)
|
expect(runState).toStrictEqual({...runState, results: runEpochResults})
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
const epochDefinitionLatl = `
|
const epochDefinitionLatl = `
|
||||||
; comment
|
; comment
|
||||||
*PROTO
|
*PROTO
|
||||||
[+ FEATURE]>[- FEATURE]/._.
|
[+ FEATURE]>[- FEATURE]/._.
|
||||||
n>m/#_.
|
n>m/#_.
|
||||||
|CHILD
|
|CHILD
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const runEpochLatl = `
|
||||||
|
; comment
|
||||||
|
*PROTO
|
||||||
|
a>u/._.
|
||||||
|
|epoch-1
|
||||||
|
`
|
||||||
|
|
||||||
|
const runEpochResults = [
|
||||||
|
{
|
||||||
|
pass: 'epoch-1',
|
||||||
|
parent: 'PROTO',
|
||||||
|
lexicon: [ 'untu', 'unut', 'unət', 'unnu', 'tun', 'əntu' ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const tokenizedEpoch = [
|
const tokenizedEpoch = [
|
||||||
{ type: "semicolon", value: "; comment" },
|
{ type: "semicolon", value: "; comment" },
|
||||||
{ type: "star", value: "*" }, { type: "referent", value: "PROTO" }, { type: 'lineBreak', value: '' },
|
{ type: "star", value: "*" }, { type: "referent", value: "PROTO" }, { type: 'lineBreak', value: '' },
|
||||||
|
|
|
@ -3,8 +3,8 @@ import {stateReducer} from './reducer';
|
||||||
describe('Lexicon', () => {
|
describe('Lexicon', () => {
|
||||||
const state = {
|
const state = {
|
||||||
epochs: [
|
epochs: [
|
||||||
{ name: 'epoch 1', changes:[''] },
|
{ name: 'epoch-1', changes:[''] },
|
||||||
{ name: 'epoch 2', changes:[''] }
|
{ name: 'epoch-2', changes:[''] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
state.lexicon = [
|
state.lexicon = [
|
||||||
|
@ -28,16 +28,16 @@ describe('Lexicon', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('lexicon addition with epoch returns updated lexicon with correct epoch', () => {
|
it('lexicon addition with epoch returns updated lexicon with correct epoch', () => {
|
||||||
const action = {type: 'ADD_LEXEME', value: {lexeme:'ntʰa', epoch: 'epoch 2'}}
|
const action = {type: 'ADD_LEXEME', value: {lexeme:'ntʰa', epoch: 'epoch-2'}}
|
||||||
expect(stateReducer(state, action)).toEqual({...state, lexicon:[...state.lexicon, {lexeme:'ntʰa', epoch:state.epochs[1]}]});
|
expect(stateReducer(state, action)).toEqual({...state, lexicon:[...state.lexicon, {lexeme:'ntʰa', epoch:state.epochs[1]}]});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('lexicon set returns updated lexicon with correct epoch', () => {
|
it('lexicon set returns updated lexicon with correct epoch', () => {
|
||||||
const newLexicon = [
|
const newLexicon = [
|
||||||
{lexeme:'anta', epoch:'epoch 1'},
|
{lexeme:'anta', epoch:'epoch-1'},
|
||||||
{lexeme:'anat', epoch:'epoch 1'},
|
{lexeme:'anat', epoch:'epoch-1'},
|
||||||
{lexeme:'anət', epoch:'epoch 1'},
|
{lexeme:'anət', epoch:'epoch-1'},
|
||||||
{lexeme:'anna', epoch:'epoch 1'}
|
{lexeme:'anna', epoch:'epoch-1'}
|
||||||
]
|
]
|
||||||
const action = {type: 'SET_LEXICON', value: newLexicon}
|
const action = {type: 'SET_LEXICON', value: newLexicon}
|
||||||
expect(stateReducer(state, action)).toEqual({...state, lexicon:[
|
expect(stateReducer(state, action)).toEqual({...state, lexicon:[
|
||||||
|
@ -58,7 +58,7 @@ describe('Lexicon', () => {
|
||||||
const inputLexicon = [
|
const inputLexicon = [
|
||||||
{lexeme:'anta'},
|
{lexeme:'anta'},
|
||||||
{lexeme:'anat'},
|
{lexeme:'anat'},
|
||||||
{lexeme:'anət', epoch:'epoch 2'},
|
{lexeme:'anət', epoch:'epoch-2'},
|
||||||
{lexeme:'anna'}
|
{lexeme:'anna'}
|
||||||
]
|
]
|
||||||
const action = {type: 'SET_LEXICON', value: inputLexicon}
|
const action = {type: 'SET_LEXICON', value: inputLexicon}
|
||||||
|
|
|
@ -263,12 +263,15 @@ export const run = (state: stateType, action: resultsAction): stateType => {
|
||||||
const passResults = state.epochs.reduce((results, epoch, _) => {
|
const passResults = state.epochs.reduce((results, epoch, _) => {
|
||||||
const { phones, features, lexicon } = state;
|
const { phones, features, lexicon } = state;
|
||||||
let lexiconBundle;
|
let lexiconBundle;
|
||||||
if ( epoch.parent && results[epoch.parent] ) {
|
if ( epoch.parent ) {
|
||||||
lexiconBundle = results.find(result => result.pass === epoch.parent).lexicon
|
lexiconBundle = results.find(result => result.pass === epoch.parent)
|
||||||
}
|
}
|
||||||
if (!epoch.parent || !results[epoch.parent]) {
|
if (!lexiconBundle) {
|
||||||
lexiconBundle = formBundleFromLexicon(lexicon)(phones);
|
lexiconBundle = formBundleFromLexicon(lexicon)(phones);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
lexiconBundle = lexiconBundle.lexicon
|
||||||
|
}
|
||||||
const ruleBundle = decomposeRules(epoch, phones);
|
const ruleBundle = decomposeRules(epoch, phones);
|
||||||
const passResults = transformLexicon(lexiconBundle)(ruleBundle)(features)
|
const passResults = transformLexicon(lexiconBundle)(ruleBundle)(features)
|
||||||
const pass = { pass: epoch.name, lexicon: passResults }
|
const pass = { pass: epoch.name, lexicon: passResults }
|
||||||
|
|
|
@ -130,7 +130,7 @@ describe('Results', () => {
|
||||||
state = initState(1)
|
state = initState(1)
|
||||||
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'
|
'anna', 'anat', 'anət', 'anna', 'tan', 'ənna'
|
||||||
]
|
]
|
||||||
|
@ -143,7 +143,7 @@ describe('Results', () => {
|
||||||
state = initState(2)
|
state = initState(2)
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'annɯ', 'anat', 'anət', 'annɯ', 'tan', 'ənnɯ'
|
'annɯ', 'anat', 'anət', 'annɯ', 'tan', 'ənnɯ'
|
||||||
]
|
]
|
||||||
|
@ -156,7 +156,7 @@ describe('Results', () => {
|
||||||
state = initState(3)
|
state = initState(3)
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'annɯ', 'anat', 'ant', 'annɯ', 'tan', 'nnɯ'
|
'annɯ', 'anat', 'ant', 'annɯ', 'tan', 'nnɯ'
|
||||||
]
|
]
|
||||||
|
@ -169,7 +169,7 @@ describe('Results', () => {
|
||||||
state = initState(4)
|
state = initState(4)
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'annɯ', 'anat', 'ant', 'annɯ', 'tʰan', 'nnɯ'
|
'annɯ', 'anat', 'ant', 'annɯ', 'tʰan', 'nnɯ'
|
||||||
]
|
]
|
||||||
|
@ -182,7 +182,7 @@ describe('Results', () => {
|
||||||
state = initState(5)
|
state = initState(5)
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'annu', 'anat', 'ant', 'annu', 'tʰan', 'nnu'
|
'annu', 'anat', 'ant', 'annu', 'tʰan', 'nnu'
|
||||||
]
|
]
|
||||||
|
@ -195,7 +195,7 @@ describe('Results', () => {
|
||||||
// state = initState(6)
|
// state = initState(6)
|
||||||
// expect(stateReducer(state, action).results).toEqual([
|
// expect(stateReducer(state, action).results).toEqual([
|
||||||
// {
|
// {
|
||||||
// pass: 'epoch 1',
|
// pass: 'epoch-1',
|
||||||
// lexicon: [
|
// lexicon: [
|
||||||
// 'annu', 'anta', 'ant', 'annu', 'tʰan', 'nnu'
|
// 'annu', 'anta', 'ant', 'annu', 'tʰan', 'nnu'
|
||||||
// ]
|
// ]
|
||||||
|
@ -207,7 +207,7 @@ describe('Results', () => {
|
||||||
const action = {type: 'RUN'};
|
const action = {type: 'RUN'};
|
||||||
state = initState(5);
|
state = initState(5);
|
||||||
const newEpoch = {
|
const newEpoch = {
|
||||||
name: 'epoch 2',
|
name: 'epoch-2',
|
||||||
changes: [
|
changes: [
|
||||||
'[+ sonorant ]>0/#_.',
|
'[+ sonorant ]>0/#_.',
|
||||||
'n>0/#_n'
|
'n>0/#_n'
|
||||||
|
@ -216,13 +216,13 @@ describe('Results', () => {
|
||||||
state.epochs = [ ...state.epochs, newEpoch ]
|
state.epochs = [ ...state.epochs, newEpoch ]
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'annu', 'anat', 'ant', 'annu', 'tʰan', 'nnu'
|
'annu', 'anat', 'ant', 'annu', 'tʰan', 'nnu'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pass: 'epoch 2',
|
pass: 'epoch-2',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'nta', 'nat', 'nət', 'na', 'tan', 'nta'
|
'nta', 'nat', 'nət', 'na', 'tan', 'nta'
|
||||||
]
|
]
|
||||||
|
@ -234,8 +234,8 @@ describe('Results', () => {
|
||||||
const action = {type: 'RUN'};
|
const action = {type: 'RUN'};
|
||||||
state = initState(5);
|
state = initState(5);
|
||||||
const newEpoch = {
|
const newEpoch = {
|
||||||
name: 'epoch 2',
|
name: 'epoch-2',
|
||||||
parent: 'epoch 1',
|
parent: 'epoch-1',
|
||||||
changes: [
|
changes: [
|
||||||
'[+ sonorant ]>0/#_.'
|
'[+ sonorant ]>0/#_.'
|
||||||
]
|
]
|
||||||
|
@ -243,14 +243,14 @@ describe('Results', () => {
|
||||||
state.epochs = [ ...state.epochs, newEpoch ]
|
state.epochs = [ ...state.epochs, newEpoch ]
|
||||||
expect(stateReducer(state, action).results).toEqual([
|
expect(stateReducer(state, action).results).toEqual([
|
||||||
{
|
{
|
||||||
pass: 'epoch 1',
|
pass: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'annu', 'anat', 'ant', 'annu', 'tʰan', 'nnu'
|
'annu', 'anat', 'ant', 'annu', 'tʰan', 'nnu'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pass: 'epoch 2',
|
pass: 'epoch-2',
|
||||||
parent: 'epoch 1',
|
parent: 'epoch-1',
|
||||||
lexicon: [
|
lexicon: [
|
||||||
'nnu', 'nat', 'nt', 'nnu', 'tʰan', 'nu'
|
'nnu', 'nat', 'nt', 'nnu', 'tʰan', 'nu'
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue