add latl parse for features
This commit is contained in:
parent
da45699c59
commit
d3ebe61577
5 changed files with 508 additions and 32 deletions
|
@ -80,9 +80,9 @@ export const addFeature = (state: stateType, action: featureAction): stateType =
|
|||
}
|
||||
|
||||
export const deleteFeature = (state, action) => {
|
||||
console.log('deleting')
|
||||
const deletedFeature = action.value;
|
||||
delete state.features[deletedFeature];
|
||||
console.log(state)
|
||||
return {...state}
|
||||
const deletedFeature = state.features[action.value];
|
||||
deletedFeature.positive.forEach(phone => delete phone.features[action.value])
|
||||
deletedFeature.negative.forEach(phone => delete phone.features[action.value])
|
||||
delete state.features[action.value];
|
||||
return state
|
||||
}
|
|
@ -31,4 +31,17 @@ describe('Features', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('feature deletion returns new feature list', () => {
|
||||
const action = {type: 'DELETE_FEATURE', value: 'occlusive'}
|
||||
expect(stateReducer(state, action)).toEqual(
|
||||
{...state,
|
||||
features: {},
|
||||
phones: {
|
||||
a: {features: {}, grapheme: 'a'},
|
||||
n: {features: {}, grapheme: 'n'}
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
});
|
|
@ -1,3 +1,5 @@
|
|||
import { stateReducer } from './reducer';
|
||||
|
||||
export const setLatl = (state, action) => {
|
||||
let latl = action.value;
|
||||
return {...state, latl, parseResults: ''};
|
||||
|
@ -47,6 +49,14 @@ const parseLineBreak = (tree, token, index, tokens) => {
|
|||
return tree;
|
||||
}
|
||||
}
|
||||
case 'feature--plus': {
|
||||
// tree[tree.length - 1].type === 'feature';
|
||||
return tree;
|
||||
}
|
||||
case 'feature--minus': {
|
||||
// tree[tree.length - 1].type === 'feature';
|
||||
return tree;
|
||||
}
|
||||
default:
|
||||
return tree;
|
||||
}
|
||||
|
@ -112,6 +122,32 @@ const parseReferent = (tree, token, index, tokens) => {
|
|||
case 'ruleSet': {
|
||||
return [...tree, { type: 'rule', value: token.value }]
|
||||
}
|
||||
case 'feature': {
|
||||
if (!lastNode.value) {
|
||||
tree[tree.length - 1].value = token.value;
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
case 'feature--plus': {
|
||||
if (lastNode.value) {
|
||||
lastNode.positivePhones = [...lastNode.positivePhones, token.value ]
|
||||
}
|
||||
else {
|
||||
lastNode.value = token.value;
|
||||
}
|
||||
tree[tree.length - 1] = lastNode;
|
||||
return [...tree]
|
||||
}
|
||||
case 'feature--minus': {
|
||||
if (lastNode.value) {
|
||||
lastNode.negativePhones = [...lastNode.negativePhones, token.value ]
|
||||
}
|
||||
else {
|
||||
lastNode.value = token.value;
|
||||
}
|
||||
tree[tree.length - 1] = lastNode;
|
||||
return [...tree]
|
||||
}
|
||||
default:
|
||||
return [...tree, `unexpected referent ${token.value}`]
|
||||
}
|
||||
|
@ -131,17 +167,26 @@ const parsePhone = (tree, token, index, tokens) => {
|
|||
|
||||
const parseOpenBracket = (tree, token, index, tokens) => {
|
||||
const lastNode = tree[tree.length - 1];
|
||||
switch (lastNode.type) {
|
||||
case 'epoch':
|
||||
return [...tree, {type: 'rule', value: token.value}]
|
||||
case 'rule':
|
||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value }
|
||||
return tree;
|
||||
case 'ruleSet':
|
||||
return [...tree, {type: 'rule', value: token.value}]
|
||||
default:
|
||||
return [...tree, 'unexpected open bracket']
|
||||
if (lastNode) {
|
||||
switch (lastNode.type) {
|
||||
case 'epoch':
|
||||
return [...tree, {type: 'rule', value: token.value}]
|
||||
case 'rule':
|
||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value }
|
||||
return tree;
|
||||
case 'ruleSet':
|
||||
return [...tree, {type: 'rule', value: token.value}];
|
||||
// case 'feature':
|
||||
// return [{type: 'feature', positivePhones: [], negativePhones: []}];
|
||||
case 'feature--plus':
|
||||
return [...tree, {type: 'feature', positivePhones: [], negativePhones: []}];
|
||||
case 'feature--minus':
|
||||
return [...tree, {type: 'feature', positivePhones: [], negativePhones: []}];
|
||||
default:
|
||||
return [...tree, 'unexpected open bracket']
|
||||
}
|
||||
}
|
||||
return [{type: 'feature', positivePhones: [], negativePhones: []}]
|
||||
}
|
||||
|
||||
const parseCloseBracket = (tree, token, index, tokens) => {
|
||||
|
@ -150,17 +195,52 @@ const parseCloseBracket = (tree, token, index, tokens) => {
|
|||
case 'rule':
|
||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value }
|
||||
return tree;
|
||||
case 'feature--plus':
|
||||
return tree;
|
||||
case 'feature--minus':
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected close bracket']
|
||||
}
|
||||
}
|
||||
|
||||
const parsePositiveAssignment = (tree, token, index, tokens) => {
|
||||
const lastNode = tree[tree.length - 1];
|
||||
switch (lastNode.type) {
|
||||
case 'feature':
|
||||
tree[tree.length - 1].type = 'feature--plus'
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected positive assignment']
|
||||
}
|
||||
}
|
||||
|
||||
const parseNegativeAssignment = (tree, token, index, tokens) => {
|
||||
const lastNode = tree[tree.length - 1];
|
||||
switch (lastNode.type) {
|
||||
case 'feature':
|
||||
tree[tree.length - 1].type = 'feature--minus'
|
||||
return tree;
|
||||
case 'feature--plus':
|
||||
tree[tree.length - 1].type = 'feature--minus';
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected negative assignment']
|
||||
}
|
||||
}
|
||||
|
||||
const parsePlus = (tree, token, index, tokens) => {
|
||||
const lastNode = tree[tree.length - 1];
|
||||
switch (lastNode.type) {
|
||||
case 'rule':
|
||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value}
|
||||
return tree;
|
||||
case 'feature':
|
||||
tree[tree.length - 1] = {...lastNode, type: 'feature--plus'}
|
||||
return tree;
|
||||
case 'feature--minus':
|
||||
tree[tree.length - 1] = {...lastNode, type: 'feature--minus'}
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected plus']
|
||||
}
|
||||
|
@ -172,11 +252,26 @@ const parseMinus = (tree, token, index, tokens) => {
|
|||
case 'rule':
|
||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value}
|
||||
return tree;
|
||||
case 'feature':
|
||||
tree[tree.length - 1] = {...lastNode, type: 'feature--minus'}
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected minus']
|
||||
}
|
||||
}
|
||||
|
||||
const parseEqual = (tree, token, index, tokens) => {
|
||||
const lastNode = tree[tree.length - 1];
|
||||
switch (lastNode.type) {
|
||||
case 'feature--plus':
|
||||
return tree;
|
||||
case 'feature--minus':
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected equal'];
|
||||
}
|
||||
}
|
||||
|
||||
const parseGreaterThan = (tree, token, index, tokens) => {
|
||||
const lastNode = tree[tree.length - 1];
|
||||
switch (lastNode.type) {
|
||||
|
@ -194,6 +289,10 @@ const parseSlash = (tree, token, index, tokens) => {
|
|||
case 'rule':
|
||||
tree[tree.length - 1] = {...lastNode, value: lastNode.value + token.value}
|
||||
return tree;
|
||||
case 'feature--plus':
|
||||
return tree;
|
||||
case 'feature--minus':
|
||||
return tree;
|
||||
default:
|
||||
return [...tree, 'unexpected slash']
|
||||
}
|
||||
|
@ -254,10 +353,16 @@ const generateNode = (tree, token, index, tokens) => {
|
|||
return parseOpenBracket(tree, token, index, tokens);
|
||||
case 'closeBracket':
|
||||
return parseCloseBracket(tree, token, index, tokens);
|
||||
case 'positiveAssignment':
|
||||
return parsePositiveAssignment(tree, token, index, tokens);
|
||||
case 'negativeAssignment':
|
||||
return parseNegativeAssignment(tree, token, index, tokens);
|
||||
case 'plus':
|
||||
return parsePlus(tree, token, index, tokens);
|
||||
case 'minus':
|
||||
return parseMinus(tree, token, index, tokens);
|
||||
case 'equal':
|
||||
return parseEqual(tree, token, index, tokens);
|
||||
case 'greaterThan':
|
||||
return parseGreaterThan(tree, token, index, tokens);
|
||||
case 'slash':
|
||||
|
@ -279,7 +384,30 @@ const connectNodes = (tree, node, index, nodes) => {
|
|||
switch (node.type) {
|
||||
case 'epoch':
|
||||
delete node.type;
|
||||
return {...tree, epochs: [...tree.epochs, {...node, index: tree.epochs.length} ]}
|
||||
return {...tree, epochs: [...tree.epochs, {...node, index: tree.epochs.length } ] }
|
||||
case 'feature':
|
||||
node.feature = node.value;
|
||||
delete node.value;
|
||||
delete node.type;
|
||||
return {...tree, features: [...tree.features, {...node } ] }
|
||||
case 'feature--minus':
|
||||
node.feature = node.value;
|
||||
delete node.value;
|
||||
delete node.type;
|
||||
if (tree.features.length && tree.features[tree.features.length - 1].feature === node.feature) {
|
||||
tree.features[tree.features.length - 1].negativePhones = node.negativePhones
|
||||
return tree;
|
||||
}
|
||||
return {...tree, features: [...tree.features, {...node} ] }
|
||||
case 'feature--plus':
|
||||
delete node.type;
|
||||
node.feature = node.value;
|
||||
delete node.value;
|
||||
if (tree.features.length && tree.features[tree.features.length - 1].feature === node.feature) {
|
||||
tree.features[tree.features.length - 1].positivePhones = node.positivePhones
|
||||
return tree;
|
||||
}
|
||||
return {...tree, features: [...tree.features, {...node} ] }
|
||||
default:
|
||||
return tree;
|
||||
}
|
||||
|
@ -288,11 +416,18 @@ const connectNodes = (tree, node, index, nodes) => {
|
|||
export const buildTree = tokens => {
|
||||
const bareTree = {
|
||||
epochs: [],
|
||||
features: [],
|
||||
phones: []
|
||||
}
|
||||
const nodes = tokens.reduce(addToken, []);
|
||||
// return nodes
|
||||
const tree = nodes.reduce(connectNodes, bareTree);
|
||||
return tree;
|
||||
const filterProps = Object.entries(tree).filter(([key, value]) => !value.length)
|
||||
.map(([key, value]) => key)
|
||||
return filterProps.reduce((tree, badProp) => {
|
||||
delete tree[badProp];
|
||||
return tree;
|
||||
}, tree);
|
||||
}
|
||||
|
||||
export const generateAST = latl => {
|
||||
|
@ -307,6 +442,16 @@ export const parseLatl = (state, action) => {
|
|||
try {
|
||||
const latl = state.latl;
|
||||
const AST = generateAST(latl);
|
||||
const features = AST.features;
|
||||
if (features) {
|
||||
if (state.features) {
|
||||
state = Object.keys(state.features).reduce((state, feature) => {
|
||||
return stateReducer(state, {type: 'DELETE_FEATURE', value: feature})
|
||||
}, state)
|
||||
}
|
||||
state = features.reduce((state, feature) => stateReducer(state, {type:'ADD_FEATURE', value: feature}), state);
|
||||
}
|
||||
delete AST.features;
|
||||
Object.entries(AST).forEach(([key, value]) => state[key] = value);
|
||||
return { ...state, parseResults: 'latl parsed successfully', results:[] }
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ describe('LATL', () => {
|
|||
expect(tokens).toStrictEqual(tokenizedEpoch)
|
||||
});
|
||||
|
||||
// it('returns tokens from well-formed latl feature definition', () => {
|
||||
// const tokens = tokenize(featureDefinitionLatl);
|
||||
// expect(tokens).toStrictEqual(tokenizedFeature);
|
||||
// });
|
||||
it('returns tokens from well-formed latl feature definition', () => {
|
||||
const tokens = tokenize(featureDefinitionLatl);
|
||||
expect(tokens).toStrictEqual(tokenizedFeature);
|
||||
});
|
||||
|
||||
// it('returns tokens from well-formed latl lexicon definition', () => {
|
||||
// const tokens = tokenize(lexiconDefinitionLatl);
|
||||
|
@ -41,6 +41,22 @@ describe('LATL', () => {
|
|||
expect(tree).toStrictEqual(treeEpoch);
|
||||
})
|
||||
|
||||
it('returns AST from well-formed feature tokens', () => {
|
||||
const tree = buildTree(tokenizedFeature);
|
||||
expect(tree).toStrictEqual(treeFeature);
|
||||
})
|
||||
|
||||
it('parse returns state from well-formed feature latl', () => {
|
||||
const state = initState();
|
||||
const setAction = {
|
||||
type: 'SET_LATL',
|
||||
value: featureDefinitionLatl
|
||||
}
|
||||
const latlState = stateReducer(state, setAction);
|
||||
const parseState = parseLatl(latlState, {});
|
||||
expect(parseState).toStrictEqual(featureState)
|
||||
})
|
||||
|
||||
it('returns run from well-formed epoch latl', () => {
|
||||
const state = initState();
|
||||
const setAction = {
|
||||
|
@ -123,18 +139,320 @@ const featureDefinitionLatl = `
|
|||
`
|
||||
|
||||
const tokenizedFeature = [
|
||||
{ type: "openBracket", value: "[" }, { type: "plus", value: "+" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "PLOSIVE" }, { type: "closeBracket", value: "]" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "equal", value: "=" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "kp" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "p" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "b" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "d" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "t" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "g" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "k" }, { type: "whiteSpace", value: "" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "openBracket", value: "[" }, { type: "minus", value: "-" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "PLOSIVE" }, { type: "closeBracket", value: "]" }, { type: "whiteSpace", value: "" },
|
||||
{type: "openBracket", value: "[" }, { type: "plus", value: "+" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "PLOSIVE" }, { type: "closeBracket", value: "]" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "equal", value: "=" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "kp" }, { type: "slash", value: "/" }, { type: "referent", value: "p" }, { type: "slash", value: "/" }, { type: "referent", value: "b" }, { type: "slash", value: "/" }, { type: "referent", value: "d" }, { type: "slash", value: "/" }, { type: "referent", value: "t" }, { type: "slash", value: "/" }, { type: "referent", value: "g" }, { type: "slash", value: "/" }, { type: "referent", value: "k" }, { type: 'lineBreak', value: '' },
|
||||
{type: "openBracket", value: "[" }, { type: "minus", value: "-" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "PLOSIVE" }, { type: "closeBracket", value: "]" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "equal", value: "=" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "m" }, { type: "slash", value: "/" }, { type: "referent", value: "n" }, { type: "slash", value: "/" }, { type: "referent", value: "s" }, { type: "slash", value: "/" }, { type: "referent", value: "z" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "openBracket", value: "[" }, { type: "referent", value: "SONORANT" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "whiteSpace", value: "" },{ type: "whiteSpace", value: "" },{ type: "positiveAssignment", value: "+=" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "referent", value: "m" }, { type: "slash", value: "/" }, { type: "whiteSpace", value: "" }, { type: "referent", value: "n" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "whiteSpace", value: "" }, { type: "whiteSpace", value: "" },{ type: "negativeAssignment", value: "-=" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "referent", value: "s" }, { type: "slash", value: "/" }, { type: "referent", value: "z" }, { type: "slash", value: "/" }, { type: "referent", value: "kp" }, { type: "slash", value: "/" }, { type: "referent", value: "p" }, { type: "slash", value: "/" }, { type: "referent", value: "b" }, { type: "slash", value: "/" }, { type: "referent", value: "d" }, { type: "slash", value: "/" }, { type: "referent", value: "t" }, { type: "slash", value: "/" }, { type: "referent", value: "g" }, { type: "slash", value: "/" }, { type: "referent", value: "k" }, { type: "whiteSpace", value: "" },{ type: 'lineBreak', value: '' },
|
||||
{type: "openBracket", value: "[" }, { type: "referent", value: "SONORANT" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "whiteSpace", value: "" }, { type: "positiveAssignment", value: "+=" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "referent", value: "m" }, { type: "slash", value: "/" }, { type: "referent", value: "n" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "whiteSpace", value: "" }, { type: "negativeAssignment", value: "-=" }, { type: "whiteSpace", value: "" },
|
||||
{ type: "referent", value: "s" }, { type: "slash", value: "/" }, { type: "referent", value: "z" }, { type: "slash", value: "/" }, { type: "referent", value: "kp" }, { type: "slash", value: "/" }, { type: "referent", value: "p" }, { type: "slash", value: "/" }, { type: "referent", value: "b" }, { type: "slash", value: "/" }, { type: "referent", value: "d" }, { type: "slash", value: "/" }, { type: "referent", value: "t" }, { type: "slash", value: "/" }, { type: "referent", value: "g" }, { type: "slash", value: "/" }, { type: "referent", value: "k" }, { type: 'lineBreak', value: '' },
|
||||
{ type: "closeBracket", value: "]" },
|
||||
]
|
||||
|
||||
const treeFeature = { features: [
|
||||
{
|
||||
feature: 'PLOSIVE',
|
||||
positivePhones: ['kp', 'p', 'b', 'd', 't', 'g', 'k'],
|
||||
negativePhones: ['m', 'n', 's', 'z']
|
||||
},
|
||||
{
|
||||
feature: 'SONORANT',
|
||||
positivePhones: ['m', 'n'],
|
||||
negativePhones: ['s' ,'z' ,'kp' ,'p' ,'b' ,'d' ,'t' ,'g' ,'k']
|
||||
}
|
||||
]}
|
||||
|
||||
const featureState = {
|
||||
...initState(),
|
||||
features: {
|
||||
PLOSIVE: {
|
||||
negative: [
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: true,
|
||||
},
|
||||
grapheme: "m",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: true,
|
||||
},
|
||||
grapheme: "n",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "s",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "z",
|
||||
},
|
||||
],
|
||||
positive: [
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
},
|
||||
grapheme: "kp",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "p",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "b",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "d",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "t",
|
||||
ʰ: {
|
||||
features: {},
|
||||
grapheme: "tʰ",
|
||||
},
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "g",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "k",
|
||||
p: {
|
||||
features: {
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "kp",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
SONORANT: {
|
||||
negative: [
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "s",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "z",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "kp",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "p",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "b",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "d",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "t",
|
||||
ʰ: {
|
||||
features: {},
|
||||
grapheme: "tʰ",
|
||||
},
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "g",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "k",
|
||||
p: {
|
||||
features: {
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "kp",
|
||||
},
|
||||
},
|
||||
],
|
||||
positive: [
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: true,
|
||||
},
|
||||
grapheme: "m",
|
||||
},
|
||||
{
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: true,
|
||||
},
|
||||
grapheme: "n",
|
||||
},
|
||||
],
|
||||
}, },
|
||||
parseResults: 'latl parsed successfully',
|
||||
latl: featureDefinitionLatl,
|
||||
phones: {
|
||||
a: {
|
||||
features: {},
|
||||
grapheme: "a",
|
||||
},
|
||||
b: {
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "b",
|
||||
},
|
||||
d: {
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "d",
|
||||
},
|
||||
g: {
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "g",
|
||||
},
|
||||
k: {
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "k",
|
||||
p: {
|
||||
features: {
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "kp",
|
||||
},
|
||||
},
|
||||
m: {
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: true,
|
||||
},
|
||||
grapheme: "m",
|
||||
},
|
||||
n: {
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: true,
|
||||
},
|
||||
grapheme: "n",
|
||||
},
|
||||
p: {
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "p",
|
||||
},
|
||||
s: {
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "s",
|
||||
},
|
||||
t: {
|
||||
features: {
|
||||
PLOSIVE: true,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "t",
|
||||
ʰ: {
|
||||
features: {},
|
||||
grapheme: "tʰ",
|
||||
},
|
||||
},
|
||||
u: {
|
||||
features: {},
|
||||
grapheme: "u",
|
||||
},
|
||||
z: {
|
||||
features: {
|
||||
PLOSIVE: false,
|
||||
SONORANT: false,
|
||||
},
|
||||
grapheme: "z",
|
||||
},
|
||||
ə: {
|
||||
features: {},
|
||||
grapheme: "ə",
|
||||
},
|
||||
ɯ: {
|
||||
features: {},
|
||||
grapheme: "ɯ",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const lexiconDefinitionLatl = `
|
||||
/PROTO
|
||||
kpn
|
||||
|
|
|
@ -211,7 +211,7 @@ const transformLexemeInitial = (newLexeme, pre, post, position, phoneme, index,
|
|||
if (!isEnvironmentBoundByRule(lexemeBundle.slice(index + position.length, index + post.length + position.length), post)) return [...newLexeme, phoneme];
|
||||
const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);
|
||||
// if deletion occurs
|
||||
if (!newPhoneme.grapheme) return [ ...newLexeme] ;
|
||||
if (!newPhoneme || !newPhoneme.grapheme) return [ ...newLexeme] ;
|
||||
return [...newLexeme, newPhoneme];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue