feature-change-applier/static/js/main.ebcfda61.chunk.js.map
2020-02-28 17:07:44 -08:00

1 line
No EOL
66 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{"version":3,"sources":["components/ProtoLang.js","components/Features.js","components/SoundChangeSuite.js","components/Epochs.js","components/Options.js","components/Output.js","reducers/reducer.lexicon.js","reducers/reducer.features.js","reducers/reducer.results.js","reducers/reducer.init.js","reducers/reducer.js","reducers/reducer.epochs.js","reducers/reducer.options.js","reducers/reducer.clear.js","PhonoChangeApplier.js","App.js","serviceWorker.js","index.js"],"names":["ProtoLang","lexicon","dispatch","className","data-testid","name","cols","rows","value","map","property","object","join","renderLexicon","onChange","e","console","log","target","split","line","lexeme","trim","epoch","type","Features","phones","features","useState","feature","setFeature","newPositivePhones","setNewPositivePhones","newNegativePhones","setNewNegativePhones","parseNewPhones","somePhones","phone","buildAddFeatureAction","positivePhones","negativePhones","featureObject","getProperty","featureMap","index","Object","keys","featureName","plus","minus","key","onClick","preventDefault","handleDeleteClick","getFeatureMapJSX","plusPhones","positive","minusPhones","negative","getFeatureMap","parsePhonesFromFeatureObject","htmlFor","id","dispatchFunction","actionBuilder","actionParameters","handleClickDispatch","SoundChangeSuite","props","epochIndex","error","removeEpoch","epochs","changes","parent","setEpoch","changeHandler","cb","updateEpoch","useEffect","renderOptionFromEpoch","thisEpoch","replaceCurrentEpoch","isViableParent","list","filter","change","onSubmit","Epochs","errors","epochName","dispatchValue","renderAddEpochButton","length","addEpoch","epochError","Options","options","handleFormSubmit","checked","output","option","setValue","handleRadioChange","handleOutputClearSubmit","Output","results","renderDefault","i","pass","renderResults","makeLexeme","state","newLexeme","findIndex","findPhone","reduce","node","graph","addFeatureToPhone","featureKey","featureValue","forEach","errorMessage","location","err","prefix","separator","decomposeRule","rule","match","lintRule","position","newFeatures","environment","pre","post","isUnknownFeatureToken","token","getFeatures","phoneme","featureBoolean","featureMatch","unknownTokens","doesFeatureRuleContainUnknownToken","bool","mapToPositiveAndNegativeFeatures","mapStringToFeatures","ruleString","ruleBrackets","v","featureBundle","lastIndex","push","findFeaturesFromGrapheme","decomposeRules","ruleBundle","mapRuleBundleToFeatureBundle","isEnvironmentBoundByRule","phonemeFeatures","ruleFeatures","ruleFeature","entries","hasOwnProperty","isPhonemeBoundByRule","getEntries","reduceFeatureValues","newPhoneme","newFeature","newValue","transformPhoneme","newPhonemeFeatures","newPhonemeCandidates","transformFeatureValues","candidates","candidatesSubset","array","candidate","includes","isObjectWithPropertyInArray","transformLexeme","lexemeBundle","find","val","slice","grapheme","transformLexemeInitial","transformLexemeCoda","formBundleFromLexicon","findFeaturesFromLexeme","stringifyLexeme","stringifyResults","passResults","run","action","_","lexiconBundle","result","transformLexicon","initState","changesArgument","a","sonorant","back","low","high","rounded","u","ɯ","ə","t","occlusive","coronal","obstruent","nasal","ʰ","aspirated","n","save","splice","stateReducer","addLexeme","newLexicon","setLexicon","newEpoch","mutatedEpochs","newFeatureName","newPhoneObject","phoneObject","addPhones","positivePhone","negativePhone","addFeature","deletedFeature","deleteFeature","mutatedState","setOptions","clearOutput","PhonoChangeApplier","useReducer","phonemes","App","Boolean","window","hostname","ReactDOM","render","document","getElementById","navigator","serviceWorker","ready","then","registration","unregister"],"mappings":"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","file":"static/js/main.ebcfda61.chunk.js","sourcesContent":["import React from 'react';\nimport './ProtoLang.scss';\n\nconst ProtoLang = ({ lexicon, dispatch }) => {\n const getProperty = property => object => object[property];\n const renderLexicon = () => {\n if (!lexicon) return '';\n // Code for optionally rendering epoch name with lexeme\n // `\\t#${lexeme.epoch.name}`\n return lexicon.map(getProperty('lexeme')).join('\\n');\n }\n\n return (\n <div className=\"ProtoLang\" data-testid=\"ProtoLang\">\n <h3>Proto Language Lexicon</h3>\n <br />\n <form data-testid=\"ProtoLang-Lexicon\">\n <textarea\n name=\"lexicon\" \n cols=\"30\"\n rows=\"10\"\n data-testid=\"ProtoLang-Lexicon__textarea\"\n value={renderLexicon()}\n onChange={e=> {\n console.log(e.target.value.split(/\\n/).map(line => {\n const lexeme = line.split('#')[0].trim();\n const epoch = line.split('#')[1] || '';\n return { lexeme, epoch }\n }))\n dispatch({\n type: 'SET_LEXICON', \n value: e.target.value.split(/\\n/).map(line => {\n const lexeme = line.split('#')[0].trim();\n const epoch = line.split('#')[1] || '';\n return { lexeme, epoch }\n })\n })\n }\n }>\n </textarea>\n </form>\n </div>\n );\n}\n\nexport default ProtoLang;","// @flow\nimport React, {useState} from 'react';\nimport './Features.scss';\n\nimport type { featureAction } from '../reducers/reducer.features';\n\n\nconst Features = ({ phones, features, dispatch }) => {\n const [feature, setFeature] = useState('aspirated')\n const [ newPositivePhones, setNewPositivePhones ] = useState('tʰ / pʰ / kʰ');\n const [ newNegativePhones, setNewNegativePhones ] = useState('t / p / k');\n \n const newFeaturesSubmit = e => {\n e.preventDefault();\n setFeature('');\n setNewPositivePhones('');\n setNewNegativePhones('');\n }\n \n const handleDeleteClick = (e, feature) => {\n e.preventDefault();\n const deleteFeatureAction = {\n type: \"DELETE_FEATURE\",\n value: feature\n }\n return dispatch(deleteFeatureAction);\n }\n \n const parsePhonesFromFeatureObject = featureObject => {\n const getProperty = property => object => object[property]\n \n const getFeatureMap = (featureObject) => {\n return Object.keys(featureObject).map(feature => {\n const plusPhones = featureObject[feature].positive.map(getProperty('grapheme')).join(' / ');\n const minusPhones = featureObject[feature].negative.map(getProperty('grapheme')).join(' / ');\n return {[feature]: {plus: plusPhones, minus: minusPhones}}\n })\n }\n \n const getFeatureMapJSX = (featureMap) => {\n return featureMap.map((feature, index) => {\n const [featureName] = Object.keys(feature);\n const { plus, minus } = feature[featureName];\n return (\n <li key={`feature__${featureName}`}>\n <span className=\"feature--names-and-phones\">\n <span className=\"feature--feature-name\"> \n {`[+ ${featureName}]`}\n </span>\n <span className=\"feature--feature-phones\">\n {plus}\n </span>\n </span>\n <span className=\"feature--names-and-phones\">\n <span className=\"feature--feature-name\"> \n {`[- ${featureName}]`}\n </span>\n <span className=\"feature--feature-phones\">\n {minus}\n </span>\n </span>\n <button className=\"delete-feature\" onClick={e => handleDeleteClick(e, featureName)}>X</button>\n </li>\n )\n })\n }\n \n const featureMap = getFeatureMap(featureObject);\n const featureMapJSX = getFeatureMapJSX(featureMap);\n return featureMapJSX;\n }\n \n const parseNewPhones = somePhones => {\n if (somePhones === '') return [''];\n return somePhones.split('/').map(phone => phone.trim());\n }\n \n const handleClickDispatch = e => dispatchFunction => actionBuilder => actionParameters => {\n e.preventDefault();\n return dispatchFunction(actionBuilder(actionParameters));\n }\n \n const buildAddFeatureAction = ([newPositivePhones, newNegativePhones, feature]): featureAction => (\n {\n type: \"ADD_FEATURE\",\n value: {\n positivePhones: parseNewPhones(newPositivePhones),\n negativePhones: parseNewPhones(newNegativePhones),\n feature\n }\n }\n )\n\n return (\n <div className=\"Features\" data-testid=\"Features\">\n \n <h3>Phonetic Features</h3>\n \n <ul className=\"Features__list\" data-testid=\"Features-list\">\n {phones ? <>{parsePhonesFromFeatureObject(features)}</> : <></>}\n </ul>\n\n <form className=\"Features__form\" data-testid=\"Features-form\">\n <input \n type=\"text\" name=\"feature\" \n value={feature} onChange={e=> setFeature(e.target.value)}\n ></input>\n\n {/* ! Positive Phones */}\n <label htmlFor=\"positive-phones\">+\n <input \n id=\"positive-phones\"\n type=\"text\" name=\"phonemes\" \n value={newPositivePhones} onChange={e=> setNewPositivePhones(e.target.value)}\n ></input>\n </label>\n \n {/* ! Negative Phones */}\n <label htmlFor=\"negative-phones\">-\n <input \n id=\"negative-phones\"\n type=\"text\" name=\"phonemes\" \n value={newNegativePhones} onChange={e=> setNewNegativePhones(e.target.value)}\n ></input>\n </label>\n\n <input \n className=\"form form--add\"\n type=\"submit\" \n onClick={e => handleClickDispatch(e)(dispatch)(buildAddFeatureAction)([newPositivePhones, newNegativePhones, feature])} \n value=\"Add feature\"\n ></input>\n </form>\n\n </div>\n );\n}\n\nexport default Features;","import React, { useState, useEffect } from 'react';\nimport './SoundChangeSuite.scss';\n\nconst SoundChangeSuite = props => {\n const { epochIndex, error, removeEpoch, epochs } = props;\n const [ epoch, setEpoch ] = useState(props.epoch ? props.epoch : {name:'', changes:[''], parent:'none'});\n \n const changeHandler = (e,cb) => {\n cb(e);\n props.updateEpoch(epoch, epochIndex);\n }\n \n useEffect(() => {\n props.updateEpoch(epoch, epochIndex);\n }, [epoch])\n\n const renderOptionFromEpoch = thisEpoch => (\n <option \n key={`${epoch.name}__parent-option--${thisEpoch.name}`}\n value={thisEpoch.name}\n >\n {thisEpoch.name}\n </option>\n )\n\n const replaceCurrentEpoch = thisEpoch => {\n if (thisEpoch.name === epoch.name) return {name: 'none'}\n return thisEpoch;\n }\n\n const isViableParent = thisEpoch => {\n if (thisEpoch.parent && thisEpoch.parent === epoch.name) return false;\n return true;\n }\n\n const parentsOptions = () => {\n return epochs.map(replaceCurrentEpoch).filter(isViableParent).map(renderOptionFromEpoch)\n }\n\n const renderParentInput = () => {\n if (epochIndex) return (\n <>\n <label htmlFor={`${epoch.name}-parent`}>\n Parent Epoch:\n </label>\n <select \n name=\"parent\"\n list={`${epoch.name}-parents-list`}\n value={epoch.parent || 'none'}\n onChange={e=>changeHandler(\n e, ()=>{\n console.log(e.target.value)\n setEpoch({...epoch, parent:e.target.value})\n })\n }\n >\n {parentsOptions()}\n </select>\n </>\n )\n return <></>\n }\n\n const renderError = () => {\n if (error) return (\n <p className=\"error\">{error}</p>\n )\n return <></>\n }\n\n return (\n <>\n <h4>{epoch.name}</h4>\n {renderError()}\n <form className=\"SoundChangeSuite__form\" data-testid={`${epoch.name}_SoundChangeSuite_changes`}>\n <label htmlFor={`${epoch.name}-name`}>\n Name: \n </label>\n <input type=\"text\" \n name=\"epoch\" \n id={`${epoch.name}-name`} cols=\"30\" rows=\"1\" \n value={epoch.name} \n onChange={e=>changeHandler(\n e, () => {\n setEpoch({...epoch, name:e.target.value})\n }\n )} \n ></input>\n {renderParentInput()}\n \n <textarea \n name=\"changes\" \n id=\"\" cols=\"30\" rows=\"10\" \n value={epoch.changes.join('\\n')} \n onChange={e=> changeHandler(\n e, ()=>setEpoch(\n {...epoch, changes:e.target.value.split(/\\n/).map(change=>change === ' ' \n ? '[+ feature]>[- feature]/_#' \n : change\n )}\n )\n )}\n ></textarea>\n </form>\n <form onSubmit={e=>removeEpoch(e, epoch.name)}>\n <input className=\"form form--remove\" type=\"submit\" name=\"remove-epoch\" value={`remove ${epoch.name}`}></input>\n </form>\n </>\n );\n}\n\nexport default SoundChangeSuite;","import React from 'react';\nimport './Epochs.scss';\n\nimport SoundChangeSuite from './SoundChangeSuite';\nimport { render } from 'react-dom';\n\n\n\nconst Epochs = ({epochs, errors, dispatch}) => {\n \n const addEpoch = e => {\n e.preventDefault()\n let index = epochs.length + 1;\n dispatch({\n type: 'ADD_EPOCH',\n value: {name: `Epoch ${index}`}\n })\n }\n\n const removeEpoch = (e, epochName) => {\n e.preventDefault()\n dispatch({\n type: 'REMOVE_EPOCH',\n value: {name: epochName}\n });\n }\n\n const updateEpoch = (epoch, epochIndex) => {\n const dispatchValue = {\n name: epoch.name,\n index: epochIndex,\n changes: epoch.changes,\n parent: epoch.parent\n }\n dispatch({\n type: \"SET_EPOCH\",\n value: dispatchValue\n })\n }\n \n const renderAddEpochButton = index => {\n if (index === epochs.length - 1 ) return (\n <form onSubmit={e=>addEpoch(e)}>\n <input className=\"form form--add\" type=\"submit\" name=\"add-epoch\" value=\"Add Epoch\" ></input>\n </form>\n )\n return <></>\n }\n\n const renderEpochs = () => {\n if (epochs.length) return epochs.map((epoch, index) => {\n const epochError = errors.epoch ? errors.error : null\n return (\n <div \n className=\"SoundChangeSuite\" \n data-testid={`${epoch.name}_SoundChangeSuite`}\n key={`epoch-${index}`}\n >\n <SoundChangeSuite \n epochIndex={index} epoch={epoch} \n updateEpoch={updateEpoch} removeEpoch={removeEpoch}\n epochs={epochs}\n error={epochError}\n />\n {renderAddEpochButton(index)}\n </div>\n )});\n return renderAddEpochButton(-1)\n }\n\n return (\n <>\n { renderEpochs() }\n </>\n );\n}\n\nexport default Epochs;","import React, { useState } from 'react';\nimport './Options.scss';\nimport ls from 'local-storage';\n\nconst Options = ({ options, dispatch }) => {\n const [ load, setLoad ] = useState('');\n\n const handleRadioChange = e => {\n const { name, id } = e.target;\n dispatch({\n type: 'SET_OPTIONS',\n value: {\n option: name,\n setValue: id\n }\n });\n }\n \n const handleFormSubmit = (e, options) => {\n e.preventDefault();\n dispatch({\n type: 'RUN',\n value: options\n });\n }\n\n const handleOutputClearSubmit = e => {\n e.preventDefault();\n console.log('clearing')\n dispatch({\n type: 'CLEAR',\n value: {}\n });\n }\n\n return (\n <div className=\"Options\" data-testid=\"Options\">\n <h3>Modeling Options</h3>\n\n <form onSubmit={e=>handleFormSubmit(e, options)} data-testid=\"Options-form\">\n <input \n type=\"radio\" name=\"output\" id=\"default\" \n checked={options ? options.output === 'default' : true}\n onChange={e=>handleRadioChange(e)}\n />\n <label htmlFor=\"default\">Default \n <span className=\"Options__output-example\"> output</span>\n </label>\n \n {/* <input \n type=\"radio\" name=\"output\" id=\"proto\" \n checked={options ? options.output === 'proto' : false}\n onChange={e=>handleRadioChange(e)}\n />\n <label htmlFor=\"proto\">Proto \n <span className=\"Options__output-example\"> output [proto]</span>\n </label>\n \n <input \n type=\"radio\" name=\"output\" id=\"diachronic\" \n checked={options ? options.output === 'diachronic' : false}\n onChange={e=>handleRadioChange(e)}\n />\n <label htmlFor=\"diachronic\">Diachronic \n <span className=\"Options__output-example\"> *proto > *epoch > output</span>\n </label> */}\n \n <input className=\"form form--add\" type=\"submit\" value=\"Run Changes\"></input>\n <input className=\"form form--remove\" type=\"button\" value=\"Clear Output\" onClick={e=>handleOutputClearSubmit(e)}/>\n </form>\n\n\n {/* <form onSubmit={()=>{}}>\n <label>\n Load from a prior run:\n <select value={load} onChange={e=>setLoad(e.target.value)}>\n {localStorage.phonoChange \n ? ls.get('phonoChange').map(priorRun => {\n return <option key={priorRun.name} value={priorRun.name}>{priorRun.name}</option>\n }\n ) : <></>}\n </select>\n </label>\n <input type=\"submit\" value=\"Submit\" />\n </form> */}\n </div>\n );\n}\n\nexport default Options;","import React from 'react';\nimport './Output.scss';\n\nconst Output = props => {\n const { results, options, errors } = props;\n const renderResults = () => {\n switch(options.output) {\n case 'default':\n return renderDefault();\n default:\n return <></>\n }\n }\n\n const renderDefault = () => {\n return results.map((epoch, i) => {\n const lexicon = epoch.lexicon.map((lexeme, i) => <span key={`${epoch.pass}-${i}`}>{lexeme}</span>);\n return (\n <div key={`epoch-${i}`} className=\"Output-epoch\">\n <h5>{epoch.pass}</h5>\n <p className=\"lexicon\">{lexicon}</p>\n </div>\n )\n })\n }\n\n return (\n <div className=\"Output\" data-testid=\"Output\">\n <h3>Results of Run</h3>\n <div data-testid=\"Output-lexicon\" className=\"Output__container\">\n {results && results.length ? renderResults() : <></>}\n </div>\n </div>\n );\n}\n\nexport default Output;","// @flow\nimport type { stateType } from './reducer';\n\ntype lexemeType = {\n lexeme: string,\n epoch?: string\n}\n\ntype addLexemeAction = {\n type: 'ADD_LEXEME',\n value: lexemeType\n}\n\ntype setLexiconAction = {\n type: 'SET_LEXICON',\n value: Array<lexemeType>\n}\n\nconst makeLexeme = (lexeme: string, epochName: ?string, state: stateType) => {\n const newLexeme = {lexeme: lexeme, epoch: state.epochs[0]};\n if (epochName) {\n const epochIndex = state.epochs.findIndex(epoch => epoch.name === epochName);\n if (epochIndex > 0) {\n newLexeme.epoch = state.epochs[epochIndex];\n };\n }\n return newLexeme;\n}\n\nexport type lexiconAction = addLexemeAction | setLexiconAction\n\nexport const addLexeme = (state: stateType, action: addLexemeAction): stateType => {\n const newLexeme = makeLexeme(action.value.lexeme, action.value.epoch, state);\n return {...state, lexicon:[...state.lexicon, newLexeme]}\n}\n\nexport const setLexicon = (state: stateType, action: setLexiconAction): stateType => {\n let newLexicon = action.value;\n newLexicon = newLexicon.map(lexeme => makeLexeme(lexeme.lexeme, lexeme.epoch, state));\n return {...state, lexicon: newLexicon}\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type featureAction = {\n type: \"ADD_FEATURE\",\n value: {\n positivePhones: Array<string>,\n negativePhones: Array<string>,\n feature: string\n }\n}\n\nconst addPhones = (phones: {}, phone: string): {} => {\n let node = {};\n\n phone.split('').forEach((graph, index) => {\n if (index) node[graph] = {}\n if (!index && !phones[graph]) phones[graph] = {} \n node = index === 0 ? phones[graph] : node[graph];\n if (index === phone.length - 1) node.grapheme = phone;\n })\n\n return phones;\n}\n\nconst findPhone = (phones: {}, phone: string): {} => {\n return phone\n .split('')\n .reduce((node, graph, index) => {\n node = index === 0 ? phones[graph] : node[graph];\n return node;\n }, {});\n}\n\nconst addFeatureToPhone = (\n phones: {}, phone: string, featureKey: string, featureValue: boolean\n): {} => {\n let node = {}\n phone.split('').forEach((graph, index) => {\n node = index === 0 ? phones[graph] : node[graph];\n \n if (index === phone.split('').length - 1) {\n node.features = {...node.features, [featureKey]: featureValue}\n }\n });\n return phones;\n}\n\nexport const addFeature = (state: stateType, action: featureAction): stateType => {\n let positivePhones = action.value.positivePhones || [];\n let negativePhones = action.value.negativePhones || [];\n let newFeatureName = action.value.feature;\n let newPhoneObject = [\n ...positivePhones, ...negativePhones\n ]\n .reduce((phoneObject, phone) => addPhones(phoneObject, phone), state.phones)\n \n if (positivePhones) {\n\n positivePhones.reduce(\n (phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, true)\n , newPhoneObject\n );\n\n positivePhones = positivePhones.map( positivePhone => findPhone(newPhoneObject, positivePhone) )\n }\n \n if (negativePhones) {\n \n negativePhones.reduce(\n (phoneObject, positivePhone) => addFeatureToPhone(phoneObject, positivePhone, newFeatureName, false)\n , newPhoneObject\n );\n \n negativePhones = negativePhones.map( negativePhone => findPhone(newPhoneObject, negativePhone) )\n }\n \n let newFeature = {[action.value.feature]: {positive: positivePhones, negative: negativePhones}};\n return {...state, features:{...state.features, ...newFeature}, phones: newPhoneObject}\n}\n\nexport const deleteFeature = (state, action) => {\n console.log('deleting')\n const deletedFeature = action.value;\n delete state.features[deletedFeature];\n console.log(state)\n return {...state}\n}","// @flow\nimport type { stateType, epochType, phoneType } from './reducer';\n\nexport type resultsAction = {\n type: 'RUN'\n}\n\nexport type decomposedRulesType = [\n {\n environment: {\n pre: [{[key: string]: boolean}],\n position: [{[key: string]: boolean}],\n post: [{[key: string]: boolean}]\n },\n newFeatures: [{[key: string]: boolean}]\n }\n]\n\ntype ruleBundle = {\n environment: {\n pre: string,\n position: string,\n post: string\n },\n newFeatures: string\n}\n\nconst getProperty = property => object => object[property]\n\nconst findFeaturesFromLexeme = (phones: {}, lexeme:string): [] => {\n let featureBundle = []\n let lastIndex = lexeme.length - 1;\n let node = {};\n [...lexeme].forEach((graph, index) => {\n if (!index) return node = phones[graph]\n if (index === lastIndex) return node[graph] \n ? featureBundle.push(node[graph])\n : featureBundle.push(node, phones[graph])\n if (!node[graph] && node.features) {\n featureBundle.push(node)\n return node = phones[graph]\n }\n if (!node[graph])\n return node = node[graph]\n })\n return featureBundle;\n}\n\nconst findFeaturesFromGrapheme = (phones: {}, lexeme:string): [] => {\n let featureBundle = []\n let lastIndex = lexeme.length - 1;\n let node = {};\n [...lexeme].forEach((graph, index) => {\n if (!index && !lastIndex) featureBundle.push(phones[graph].features)\n if (!index) return node = phones[graph]\n if (index === lastIndex) return node[graph] \n ? featureBundle.push(node[graph])\n : featureBundle.push(node, phones[graph])\n if (!node[graph] && node.features) {\n featureBundle.push(node)\n return node = phones[graph]\n }\n if (!node[graph])\n return node = node[graph]\n })\n return featureBundle;\n}\n\nconst errorMessage = ([prefix, separator], location, err) => `${prefix}${location}${separator}${err}`\n\nconst lintRule = (rule) => {\n if (!rule.match(/>/g)) throw `Insert '>' operator between target and result`\n if (!rule.match(/\\//g)) throw `Insert '/' operator between change and environment`\n if (!rule.match(/_/g)) throw `Insert '_' operator in environment`\n if (rule.match(/>/g).length > 1) throw `Too many '>' operators`\n if (rule.match(/\\//g).length > 1) throw `Too many '/' operators`\n if (rule.match(/_/g).length > 1) throw `Too many '_' operators`\n return rule.split(/>|\\/|_/g);\n}\n\nconst decomposeRule = (rule: string, index: number): ruleBundle => {\n try {\n // splits rule at '>' '/' and '_' substrings resulting in array of length 4\n const [position, newFeatures, pre, post] = lintRule(rule); \n return { environment: { pre, position, post }, newFeatures }\n } catch (err) {\n throw errorMessage`Error in line ${index + 1}: ${err}`;\n }\n}\n\nconst isUnknownFeatureToken = token => token !== '-' && token !== '+' && token !== ']' && token !== '[' && token !== ' ';\n\nconst doesFeatureRuleContainUnknownToken = features => {\n const unknownTokens = features\n .match(/\\W/g)\n .filter(isUnknownFeatureToken)\n if (unknownTokens.length) throw `Unknown token '${unknownTokens[0]}'`;\n return true\n}\n\nconst reduceFeaturesToBoolean = bool => (map, feature) => ({...map, [feature]: bool})\n\nconst getFeatures = (phoneme: string, featureBoolean): {} => {\n try {\n const featureMatch = featureBoolean\n // regEx to pull positive features\n ? /(?=\\+.).*(?<=\\-)|(?=\\+.).*(?!\\-).*(?<=\\])/g \n // regEx to pull negative features\n : /(?=\\-.).*(?<=\\+)|(?=\\-.).*(?!\\+).*(?<=\\])/g\n const [ features ] = phoneme.match(featureMatch) || [ null ];\n if (features) {\n doesFeatureRuleContainUnknownToken(features)\n return features\n .trim()\n .match(/\\w+/g)\n .reduce(reduceFeaturesToBoolean(featureBoolean), {})\n }\n return {}\n } catch (err) {\n throw err;\n }\n}\n\nconst mapToPositiveAndNegativeFeatures = phoneme => (\n { ...getFeatures(phoneme, true), ...getFeatures(phoneme, false) } )\n\nconst mapStringToFeatures = (ruleString, phones) => {\n if (ruleString) {\n if (ruleString === '.') return [];\n if (ruleString === '#') return ['#']\n if (ruleString === '0') return [];\n const ruleBrackets = ruleString.match(/\\[.*\\]/)\n try {\n if (ruleBrackets) {\n return ruleString\n .split('[')\n // filter out empty strings\n .filter(v => v)\n .map(mapToPositiveAndNegativeFeatures)\n }\n return findFeaturesFromGrapheme(phones, ruleString);\n } catch (err) {\n throw err;\n }\n }\n return {};\n}\n\nconst mapRuleBundleToFeatureBundle = phones => ( ruleBundle, index ) => {\n // for each object in ruleBundle, map values to array of objects with feature-boolean key-value pairs\n try {\n const { newFeatures, environment:{ pre, position, post } } = ruleBundle;\n return {\n environment: {\n pre: mapStringToFeatures(pre, phones),\n position: mapStringToFeatures(position, phones),\n post: mapStringToFeatures(post, phones),\n },\n newFeatures: mapStringToFeatures(newFeatures, phones)\n }\n } catch (err) {\n throw errorMessage`Error in line ${index + 1}: ${err}`;\n }\n}\n\nexport const decomposeRules = (epoch: epochType, phones: {[key: string]: phoneType}): decomposedRulesType => {\n const { changes } = epoch\n try {\n return changes\n .map(decomposeRule)\n .map(mapRuleBundleToFeatureBundle(phones));\n } catch (err) {\n const ruleError = {epoch: epoch.name, error: err}\n throw ruleError;\n }\n}\n\nconst isPhonemeBoundByRule = phonemeFeatures => (ruleFeature, index) => {\n const phoneme = phonemeFeatures[index].features;\n return Object.entries(ruleFeature).reduce((bool, [feature, value]) => {\n if (!bool) return false;\n if (!phoneme.hasOwnProperty(feature)) return false;\n if (!phoneme[feature] && !value) return true;\n if (phoneme[feature] !== value) return false;\n return true;\n }, true);\n} \n\nconst isEnvironmentBoundByRule = (phonemeFeatures, ruleFeatures) => {\n if (!ruleFeatures) return true;\n return ruleFeatures.filter(isPhonemeBoundByRule(phonemeFeatures)).length === ruleFeatures.length;\n}\n\nconst getEntries = object => Object.entries(object);\nconst isObjectWithPropertyInArray = (array, property) => candidate => array.map(getProperty(property)).includes(candidate[property]);\nconst transformFeatureValues = features => ([newFeature, newValue]) => features[newFeature][newValue ? 'positive': 'negative'];\nconst reduceFeatureValues = (newPhoneme, [newFeature, newValue]) => ({ ...newPhoneme, [newFeature]: newValue })\n\nconst transformPhoneme = (phoneme, newFeatures, features) => {\n if (!newFeatures) return {}\n const newPhonemeFeatures = getEntries(newFeatures).reduce(reduceFeatureValues, {...phoneme.features});\n const newPhonemeCandidates = getEntries(newPhonemeFeatures).map(transformFeatureValues(features));\n return newPhonemeCandidates\n .reduce((candidates, candidatesSubset, index, array) => candidates.filter(isObjectWithPropertyInArray(candidatesSubset, 'grapheme'))\n , newPhonemeCandidates[newPhonemeCandidates.length - 1])[0];\n}\n\nconst transformLexemeInitial = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {\n if (index !== pre.length - 1) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index + position.length, index + post.length + position.length), post)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n}\n\nconst transformLexemeCoda = (newLexeme, pre, post, position, phoneme, index, lexemeBundle, newFeatures, features) => {\n if (index + post.length !== lexemeBundle.length) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n}\n\nexport const transformLexeme = (lexemeBundle, rule, features) => {\n const {pre, post, position} = rule.environment;\n const newLexeme = lexemeBundle.reduce((newLexeme, phoneme, index) => {\n if (pre.find(val => val === '#')) return transformLexemeInitial(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);\n if (post.find(val => val === '#')) return transformLexemeCoda(newLexeme, pre, post, position, phoneme, index, lexemeBundle, rule.newFeatures, features);\n if ( index < pre.length || index >= lexemeBundle.length - post.length ) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index - pre.length, index), pre)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule([phoneme], position)) return [...newLexeme, phoneme];\n if (!isEnvironmentBoundByRule(lexemeBundle.slice(index, index + post.length), post)) return [...newLexeme, phoneme];\n const newPhoneme = transformPhoneme(phoneme, rule.newFeatures[0], features);\n // if deletion occurs\n if (!newPhoneme || !newPhoneme.grapheme) return [ ...newLexeme] ;\n return [...newLexeme, newPhoneme];\n }, [])\n return newLexeme;\n}\n\nconst formBundleFromLexicon = lexicon => phones => lexicon.map(({lexeme}) => findFeaturesFromLexeme(phones, lexeme))\n\nconst transformLexicon = lexiconBundle => \n ruleBundle => \n features => \n lexiconBundle.map(lexemeBundle => ruleBundle.reduce(\n (lexeme, rule, i) => transformLexeme(lexeme, rule, features)\n , lexemeBundle\n ))\n\nconst getGraphemeFromEntry = ([_, phoneme]) => phoneme.grapheme\nconst stringifyLexeme = (lexeme) => lexeme.map(getProperty('grapheme')).join('')\nconst stringifyResults = ({lexicon, ...passResults}) => ({...passResults, lexicon: lexicon.map(stringifyLexeme)})\n\nexport const run = (state: stateType, action: resultsAction): stateType => {\n\n // TODO iterate through each epoch\n try {\n const passResults = state.epochs.reduce((results, epoch, _) => {\n const { phones, features, lexicon } = state;\n let lexiconBundle;\n if ( epoch.parent ) {\n lexiconBundle = results.find(result => result.pass === epoch.parent).lexicon\n }\n if (!epoch.parent) {\n lexiconBundle = formBundleFromLexicon(lexicon)(phones); \n }\n const ruleBundle = decomposeRules(epoch, phones);\n const passResults = transformLexicon(lexiconBundle)(ruleBundle)(features)\n const pass = { pass: epoch.name, lexicon: passResults }\n if ( epoch.parent ) pass.parent = epoch.parent;\n return [...results, pass];\n }, []);\n \n const results = passResults.map(stringifyResults);\n return {...state, results, errors: {} }\n } catch (err) {\n console.log(err)\n return {...state, errors: err, results:[] };\n }\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type initAction = {\n type: \"INIT\"\n}\n\nexport const initState = (changesArgument: number): stateType => {\n const state = {\n epochs: [\n {\n name: 'epoch 1',\n changes: [\n '[+ occlusive - nasal]>[+ occlusive + nasal]/n_.',\n 'a>ɯ/._#',\n '[+ sonorant - low rounded high back]>0/._.',\n '[+ obstruent]>[+ obstruent aspirated ]/#_.',\n '[+ sonorant - rounded]>[+ sonorant + rounded]/._#',\n // 'at>ta/._#'\n ]\n }\n ],\n phones: {\n a: {\n grapheme: 'a', features: {\n sonorant: true, back: true, low: true, high: false, rounded: false\n }\n },\n u: {\n grapheme: 'u', features: {\n sonorant: true, back: true, low: false, high: true, rounded: true, \n }\n },\n ɯ: {\n grapheme: 'ɯ', features: {\n sonorant: true, back: true, low: false, high: true, rounded: false,\n }\n },\n ə: {\n grapheme: 'ə', features: {\n sonorant: true, low: false, rounded: false, high: false, back: false\n }\n },\n t: {\n grapheme: 't', features: {\n occlusive: true, coronal: true, obstruent: true, nasal: false\n },\n ʰ: {\n grapheme: 'tʰ', features: {\n occlusive: true, coronal: true, obstruent: true, aspirated: true\n }\n }\n },\n n: {\n grapheme: 'n', features: {\n sonorant: true, nasal: true, occlusive: true, coronal: true\n }\n }\n },\n options: {\n output: 'default', save: false\n },\n results: [],\n errors: {},\n features: {},\n lexicon: []\n };\n state.features = {\n sonorant: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ, state.phones.ə, state.phones.n], negative: [] },\n back: { positive:[ state.phones.a, state.phones.u, state.phones.ɯ ], negative: [ state.phones.ə ] },\n low: { positive:[ state.phones.a ], negative: [ state.phones.u, state.phones.ɯ, state.phones.ə ] },\n high: { positive:[ state.phones.u, state.phones.ɯ ], negative: [ state.phones.a, state.phones.ə ] },\n rounded: { positive:[ state.phones.u ], negative: [ state.phones.a, state.phones.ɯ, state.phones.ə ] },\n occlusive: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n coronal: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n obstruent: { positive:[ state.phones.t, state.phones.n, state.phones.t.ʰ ], negative: [] },\n nasal: { positive:[ state.phones.n ], negative: [state.phones.t, state.phones.t.ʰ] },\n aspirated: { positive:[ state.phones.t.ʰ ], negative: [ state.phones.t ] },\n }\n state.lexicon = [\n {lexeme: 'anta', epoch: state.epochs[0]}, \n {lexeme: 'anat', epoch: state.epochs[0]},\n {lexeme: 'anət', epoch: state.epochs[0]},\n {lexeme: 'anna', epoch: state.epochs[0]}, \n {lexeme: 'tan', epoch: state.epochs[0]},\n {lexeme: 'ənta', epoch: state.epochs[0]}\n ]\n\n if(changesArgument > -1) state.epochs[0].changes = state.epochs[0].changes.splice(0, changesArgument)\n\n return state;\n}","// @flow\nimport { addLexeme, setLexicon } from './reducer.lexicon';\nimport type { lexiconAction } from './reducer.lexicon';\nimport { addEpoch, setEpoch, removeEpoch } from './reducer.epochs';\nimport type { epochAction } from './reducer.epochs';\nimport { addFeature, deleteFeature } from './reducer.features';\nimport type { featureAction } from './reducer.features';\nimport type { optionsAction } from './reducer.options';\nimport { setOptions } from './reducer.options';\nimport { run } from './reducer.results';\nimport type { resultsAction } from './reducer.results'\nimport { initState } from './reducer.init';\nimport type { initAction } from './reducer.init';\nimport { clearOutput } from './reducer.clear';\n\nexport type stateType = {\n lexicon: Array<{lexeme: string, epoch: epochType}>,\n epochs: Array<epochType>,\n phones: {[key: string]: phoneType},\n options: {output: string, save: boolean},\n results: [],\n errors: {},\n features: featureType\n}\n\ntype epochType = {\n name: string, changes: Array<string>\n}\n\ntype phoneType = {\n grapheme: string,\n features: {[key: string]: boolean}\n}\n\ntype featureType = {\n [key: string]: {[key: string]: Array<phoneType>}\n}\n\ntype actionType = featureAction | epochAction | initAction | resultsAction | lexiconAction\n\nexport const stateReducer = (state: stateType, action: actionType): stateType => {\n switch (action.type) {\n case 'INIT': {\n return initState();\n }\n \n case 'ADD_LEXEME': return addLexeme(state, action);\n \n case 'SET_LEXICON': return setLexicon(state, action);\n\n case 'ADD_EPOCH': return addEpoch(state, action);\n\n case 'SET_EPOCH': return setEpoch(state, action);\n\n case 'REMOVE_EPOCH': return removeEpoch(state, action);\n\n case 'ADD_FEATURE': return addFeature(state, action);\n\n case 'DELETE_FEATURE': return deleteFeature(state, action);\n\n case 'SET_OPTIONS': return setOptions(state, action);\n\n case 'CLEAR': return clearOutput(state, action);\n\n case 'RUN': return run(state, action);\n\n default: return state;\n }\n}\n","// @flow\nimport type { stateType } from './reducer';\n\nexport type epochAction = {\n type: \"ADD_EPOCH\" | \"SET_EPOCH\" | \"REMOVE_EPOCH\",\n value: {\n index?: number,\n name: string,\n changes?: Array<string>,\n parent?: string\n }\n}\n\nexport const addEpoch = (state: stateType, action: epochAction): stateType => {\n const newEpoch = { name: action.value.name, changes: action.value.changes || [''], parent: null};\n return {...state, epochs: [...state.epochs, newEpoch]}\n}\n\nexport const setEpoch = (state: stateType, action: epochAction): stateType => {\n const index = action.value.index;\n if (typeof index !== 'number') return state;\n \n const mutatedEpochs = state.epochs;\n mutatedEpochs[index].name = action.value.name \n ? action.value.name \n : mutatedEpochs[index].name;\n\n mutatedEpochs[index].changes = action.value.changes \n ? action.value.changes \n : mutatedEpochs[index].changes;\n\n mutatedEpochs[index].parent = action.value.parent && action.value.parent !== 'none'\n ? action.value.parent\n : null\n return {...state, epochs: [...mutatedEpochs]}\n}\n\nexport const removeEpoch = (state: stateType, action: epochAction): stateType => {\n const mutatedEpochs = state.epochs.filter(epoch => epoch.name !== action.value.name )\n return {...state, epochs: [...mutatedEpochs]}\n}","// @flow\nimport type { stateType } from './reducer';\n\nexport type optionAction = {\n type: 'SET_OPTIONS',\n value: {\n option: string,\n setValue: string\n }\n};\n\nexport const setOptions = (state: stateType, action: optionAction): stateType => {\n const option = action.value.option;\n let value = action.value.setValue;\n if (value === 'true') value = true;\n if (value === 'false') value = false;\n const mutatedState = {...state};\n mutatedState.options[option] = value;\n return mutatedState;\n}","export const clearOutput = (state, action) => {\n return { ...state, results: [], errors: {} };\n}","import React, { useState, useReducer } from 'react';\nimport './PhonoChangeApplier.scss';\n\nimport ProtoLang from './components/ProtoLang';\nimport Features from './components/Features';\nimport Epochs from './components/Epochs';\nimport Options from './components/Options';\nimport Output from './components/Output';\n\nimport { stateReducer } from './reducers/reducer';\nimport { initState } from './reducers/reducer.init';\n\nconst PhonoChangeApplier = () => {\n const [ state, dispatch ] = useReducer(\n stateReducer,\n {},\n initState\n )\n const { lexicon, phones, phonemes, epochs, options, features, results, errors } = state;\n\n return (\n <div className=\"PhonoChangeApplier\" data-testid=\"PhonoChangeApplier\">\n <ProtoLang lexicon={lexicon} dispatch={dispatch}/>\n <Features phones={phones} features={features} dispatch={dispatch}/>\n <Epochs epochs={epochs} errors={errors} dispatch={dispatch} />\n <Options options={options} dispatch={dispatch}/>\n <Output results={results} options={options} dispatch={dispatch}/>\n </div>\n );\n}\n\nexport default PhonoChangeApplier;","import React from 'react';\nimport './App.css';\nimport PhonoChangeApplier from './PhonoChangeApplier';\n\nfunction App() {\n return (\n <div className=\"App\" data-testid=\"App\">\n <h1>Feature Change Applier</h1>\n <PhonoChangeApplier />\n </div>\n );\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.1/8 is considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl)\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister();\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.scss';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(<App />, document.getElementById('root'));\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}