Skip to content

Commit

Permalink
Add noun-possessives morpho paradigm. Add route for obtaining paradig…
Browse files Browse the repository at this point in the history
…ms and their inputs.
  • Loading branch information
johnjcamilleri committed Apr 13, 2020
1 parent 0330f95 commit 1d388c2
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 35 deletions.
63 changes: 63 additions & 0 deletions morpho/noun-possessives.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var extend = require('extend')
module.exports = {

sourceKey: 'Camilleri2020',

inflect: function (body, callback) {
var lemma = body.lemma // omm
if (!lemma) {
return callback(new Error('No lemma provided'), null)
}

let stem
if (lemma.endsWith('a')) { // kelma
stem = lemma.slice(0, -1) + 't' // kelmt-
} else {
stem = lemma
}
var forms = [
{
'surface_form': stem.endsWith('u') ? `${stem}wi` : `${stem}i`, // nannuwi, ommi
'possessor': { 'person': 'p1', 'number': 'sg' }
},
{
'surface_form': stem.match(/[aeiou]$/) ? `${stem}k` : stem.includes('o') ? `${stem}ok` : `${stem}ek`, // nannuk, ommok, kelmtek
'possessor': { 'person': 'p2', 'number': 'sg' }
},
{
'surface_form': stem.match(/[aeiou]$/) ? `${stem}h` : `${stem}u`, // nannuh, ommu
'possessor': { 'person': 'p3', 'number': 'sg', 'gender': 'm' }
},
{
'surface_form': `${stem}ha`, // ommha
'possessor': { 'person': 'p3', 'number': 'sg', 'gender': 'f' }
},
{
'surface_form': `${stem}na`, // ommna
'possessor': { 'person': 'p1', 'number': 'pl' }
},
{
'surface_form': `${stem}kom`, // ommkom
'possessor': { 'person': 'p2', 'number': 'pl' }
},
{
'surface_form': `${stem}hom`, // ommhom
'possessor': { 'person': 'p3', 'number': 'pl' }
}
]
var extras = {
'sources': [this.sourceKey]
}
if (body.hasOwnProperty('gender')) {
extras['gender'] = body.gender
}
if (body.hasOwnProperty('number')) {
extras['number'] = body.number
}
for (let f in forms) {
extend(true, forms[f], extras)
}

callback(null, forms)
}
}
23 changes: 12 additions & 11 deletions public/markdown/api-admin.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,23 @@ Non-public API for editing. These methods generally require authorisation.
| `GET` | `/lexemes/:id` | Read | - | Document |
| `POST` | `/lexemes/:id` | Update | Entire document | Document |
| `POST` | `/lexemes/set/:id` | Set/update individual fields | Document with fields to update | Document |
| `POST` | `/lexemes/unset/:id` | Remove inidividual fields | Documnet with fields to remove (values ignored) | Document |
| `POST` | `/lexemes/unset/:id` | Remove inidividual fields | Document with fields to remove (values ignored) | Document |
| `DELETE` | `/lexemes/:id` | Delete (including wordforms) | - | - |


## Wordforms

| Method | URL | Description | Payload* | Return Value |
|:---------|:--------------------------------------------|:---------------------------------------------------------------|:-----------------------------------------------------------|:--------------------|
| `POST` | `/wordforms/` | Create | Entire document | Document |
| `GET` | `/wordforms/:id` | Read | - | Document |
| `POST` | `/wordforms/:id` | Update | Entire document | Document |
| `POST` | `/wordforms/set/:id` | Set/update individual fields | Document with fields to update | Document |
| `POST` | `/wordforms/unset/:id` | Remove inidividual fields | Documnet with fields to remove (values ignored) | Document |
| `DELETE` | `/wordforms/:id` | Delete | - | - |
| `POST` | `/wordforms/replace/:lexeme_id` | Search/replace in wordforms | `{search: (string), replace: (string), commit: (boolean)}` | Affected documents |
| `POST` | `/wordforms/generate/:paradigm/:lexeme_id?` | Generate inflections (`lexeme_id` is required when committing) | `{lemma: (string), commit: (boolean)}` | Generated documents |
| Method | URL | Description | Payload* | Return Value |
|:---------|:--------------------------------------------|:---------------------------------------------------------------|:-----------------------------------------------------------|:-------------------------------------|
| `POST` | `/wordforms/` | Create | Entire document | Document |
| `GET` | `/wordforms/:id` | Read | - | Document |
| `POST` | `/wordforms/:id` | Update | Entire document | Document |
| `POST` | `/wordforms/set/:id` | Set/update individual fields | Document with fields to update | Document |
| `POST` | `/wordforms/unset/:id` | Remove inidividual fields | Documnet with fields to remove (values ignored) | Document |
| `DELETE` | `/wordforms/:id` | Delete | - | - |
| `POST` | `/wordforms/replace/:lexeme_id` | Search/replace in wordforms | `{search: (string), replace: (string), commit: (boolean)}` | Affected documents |
| `GET` | `/wordforms/generate` | List inflection paradigms | - | Paradigms with their expected fields |
| `POST` | `/wordforms/generate/:paradigm/:lexeme_id?` | Generate inflections (`lexeme_id` is required when committing) | `{lemma: (string), commit: (boolean)}` | Generated documents |

## Roots

Expand Down
43 changes: 31 additions & 12 deletions routes/wordforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,33 @@ var sortWordforms = require('./helpers/sort-wordforms')

// -- Morphological generation -----------------------------------------------

/* Generate */
// Must match filenames in ../morpho/
const paradigms = [
{
name: 'loan-verb',
fields: ['lemma']
},
{
name: 'adjective',
fields: ['lemma']
},
{
name: 'noun',
fields: ['lemma']
},
{
name: 'noun-possessives',
fields: ['lemma', 'number', 'gender']
}
]
const paradigmNames = paradigms.map(p => p.name)

/* List generation paradigms */
router.get('/generate', function (req, res, next) {
res.json(paradigms)
})

/* Run generation */
/* Content-Type: application/json */
router.post('/generate/:paradigm/:lexeme_id?',
passport.authenticate('basic', {
Expand All @@ -19,18 +45,11 @@ router.post('/generate/:paradigm/:lexeme_id?',
function (req, res, next) {
// Load inflector dynamically
var par = req.params.paradigm
var mg
switch (par) {
case 'loan-verb':
case 'adjective':
case 'noun':
mg = require('../morpho/' + par)
break
default:
res.status(400).send('Unknown paradigm ' + par)
return
if (!paradigmNames.contains(par)) {
res.status(400).send('Unknown paradigm ' + par)
return
}

var mg = require('../morpho/' + par)
mg.inflect(req.body, function (err, forms) {
if (err) {
res.status(400).send(err)
Expand Down
115 changes: 103 additions & 12 deletions test/morpho.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ function contains (forms, form) {
}, `${JSON.stringify(form)} not found in forms`)
}

// Convert array index to agr object
function toAgr (ix) {
return [
{'person': 'p1', 'number': 'sg'},
{'person': 'p2', 'number': 'sg'},
{'person': 'p3', 'number': 'sg', 'gender': 'm'},
{'person': 'p3', 'number': 'sg', 'gender': 'f'},
{'person': 'p1', 'number': 'pl'},
{'person': 'p2', 'number': 'pl'},
{'person': 'p3', 'number': 'pl'}
][ix]
}

/* Tests for feedback functionality */
describe('Morphological generation', function () {
describe('Adjectives', function () {
Expand Down Expand Up @@ -96,21 +109,99 @@ describe('Morphological generation', function () {
})
})

describe('Loan verbs', function () {
const gen = require('../morpho/loan-verb')
describe('Noun possessives', function () {
const gen = require('../morpho/noun-possessives')

function toAgr (ix) {
return [
{'person': 'p1', 'number': 'sg'},
{'person': 'p2', 'number': 'sg'},
{'person': 'p3', 'number': 'sg', 'gender': 'm'},
{'person': 'p3', 'number': 'sg', 'gender': 'f'},
{'person': 'p1', 'number': 'pl'},
{'person': 'p2', 'number': 'pl'},
{'person': 'p3', 'number': 'pl'}
][ix]
function check (doc, goldforms, done) {
gen.inflect(
doc,
function (err, forms) {
if (err) {
done(err)
return
}
for (let ix in goldforms) {
let gold = {
'surface_form': goldforms[ix],
'possessor': toAgr(ix)
}
if (doc.hasOwnProperty('gender')) gold['gender'] = doc.gender
if (doc.hasOwnProperty('number')) gold['number'] = doc.number
contains(forms, gold)
}
done()
}
)
}

it('omm', function (done) {
check({
'lemma': 'omm',
'gender': 'f',
'number': 'sg'
}, [
'ommi',
'ommok',
'ommu',
'ommha',
'ommna',
'ommkom',
'ommhom'
],
done)
})
it('kelma', function (done) {
check({
'lemma': 'kelma',
'gender': 'f',
'number': 'sg'
}, [
'kelmti',
'kelmtek',
'kelmtu',
'kelmtha',
'kelmtna',
'kelmtkom',
'kelmthom'
],
done)
})
it('nannu', function (done) {
check({
'lemma': 'nannu',
'gender': 'm',
'number': 'sg'
}, [
'nannuwi',
'nannuk',
'nannuh',
'nannuha',
'nannuna',
'nannukom',
'nannuhom'
],
done)
})
it('nanniet', function (done) {
check({
'lemma': 'nanniet',
'number': 'pl'
}, [
'nannieti',
'nannietek',
'nannietu',
'nannietha',
'nannietna',
'nannietkom',
'nanniethom'
],
done)
})
})

describe('Loan verbs', function () {
const gen = require('../morpho/loan-verb')

function check (lemma, tbl, done) {
gen.inflect(
{lemma: lemma},
Expand Down

0 comments on commit 1d388c2

Please sign in to comment.