test green for run from parsed epoch latl

This commit is contained in:
Sorrel Bri 2020-03-02 19:06:21 -08:00
parent 35f815a9c9
commit 49419a39ee
7 changed files with 65 additions and 47 deletions

View file

@ -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}]
}); });
}); });

View file

@ -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>ɯ/._#',

View file

@ -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+`]

View file

@ -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: '' },

View file

@ -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}

View file

@ -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 }

View file

@ -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'
] ]