Lexurgy Sound Changer Tutorial — Building Complex Rules

Simultaneous Expressions

Recall that Lexurgy applies rules one after the other, from top to bottom:

Ready
Input WordOutput Word

The first rule changes the p in ampa to a b, and then the second rule changes it all the way to m, so both words end up containing mm.

But if you write these two expressions in the same rule, Lexurgy will run them simultaneously. Later expressions don't see the effects of earlier expressions:

Ready
Input WordOutput Word

Now the first expression matches ampa and changes it to amba, while the second expression matches imbi and changes it to immi. The second expression never gets a chance to apply to amba.

Since the expressions run simultaneously, their order often doesn't matter. But if two expressions try to change the same part of the word, the first expression takes precedence. This can be useful for making rules that do one thing in most cases, and another thing in some exceptional case:

Ready
Input WordOutput Word

Multi-Step Rules

You may also want to combine rules without making them run simultaneously; this can make it clearer that you think of all the expressions as really being part of the same sound change. You do this by putting then: between the expressions:

Ready
Input WordOutput Word

Filters

Sometimes, you only care about certain kinds of sounds, and want to ignore anything else. For example, this umlaut rule will apply across any number of intervening consonants:

Ready
Input WordOutput Word

Anything that isn't in the @vowel class is ignored when determining which sounds are adjacent. Even though the condition is _ i, i.e. "when immediately before an i", the rule applies to the a in bapski, because that a is immediately before the i if you ignore all the non-vowels. But the first a in bapaski is unaffected, since there's another vowel between it and the i.

Propagation

You may find that a change creates more opportunities for the same change to apply. Suppose you have a language that has just deleted a lot of word-internal consonants:

Ready
Input WordOutput Word

This creates many sequences of vowels in hiatus. You may want to simplify these sequences by combining them according to a chart:

Ready
Input WordOutput Word

But what if there are several dropped consonants in a row?

Ready
Input WordOutput Word

Now there are still vowels in hiatus. The hiatus simplification rule matched the first ii in kiii and the aa in buaai, changed that, and stopped.

But if you mark the rule with the propagate modifier, it keeps going until there's nothing more to match:

Ready
Input WordOutput Word

Controlling Propagation Direction

Propagation is very powerful, but sometimes you want propagation to go in one direction only. Take this example:

Ready
Input WordOutput Word

You're trying to get kwiwi, but it comes out as kujui. That's because the iu => ju part of the hiatus simplification rule has a higher priority than the ui => wi part, so the rule finds the iu in the middle first and changes it, blocking anything else from changing.

If you replace propagate with ltr ("Left To Right") though:

Ready
Input WordOutput Word

You get the intended result. The rule now starts at the beginning of the word and sweeps to the right, applying changes as it goes. So it finds the first ui first and changes it to wi, which blocks the unwanted iu => ju change. Then it finds the second ui and changes that to wi too.

The ltr modifier is also useful for rules like vowel harmony, which spread from one end of the word to the other:

Ready
Input WordOutput Word

For propagation from the end of the word to the beginning, use the rtl modifier:

Ready
Input WordOutput Word

Reusable Elements

If you find yourself repeating part of an expression across many rules, consider declaring it as an element.

Element declarations are similar to class declarations, but they can contain anything that you could find in an expression. Once declared, you reference elements using the same @ syntax as referencing classes:

Ready
Input WordOutput Word

Reusable Rules

If you find yourself applying the same sound changes at several stages of your language's evolution, consider turning them into deferred rules. A deferred rule isn't applied where it's declared; instead, you apply it later as part of other rules.

For example, suppose you have a nasal assimilation rule:

Ready
Input WordOutput Word

Then you go on developing your language, and at some point you have a vowel deletion rule:

Ready
Input WordOutput Word

But this reintroduces nasal-stop clusters at different places of articulation. To fix this, you apply the nasal assimilation rule again. Now you have these sound changes:

Ready
Input WordOutput Word

That works, but it's annoying; this entire rule appears twice, cluttering up your sound changes. It also means that if you later find a mistake in this rule, you have to remember to fix the mistake in both places. And this will only get worse if you later have to apply the nasal assimilation rule a third time...

You can get rid of this repetition by declaring nasal assimilation as a deferred rule:

Ready
Input WordOutput Word

Deferred rules aren't applied at the point where they're declared; you trigger them by referencing them from other rules. Here, the initial-nasal-assimilation and nasal-assimilation-again rules both reference the deferred nasal-assimilation rule.

Cleanup Rules

Sometimes you don't need the precision of a deferred rule; you want something like nasal assimilation to apply after every rule, to clean up any illicit clusters. You can do this by declaring nasal-assimilation to be a cleanup rule:

Ready
Input WordOutput Word

Cleanup rules run once when declared, and then again after every subsequent named rule.

If you want a cleanup rule to stop applying at some point, you can turn it off:

Ready
Input WordOutput Word

Romanization

It's a good idea to do all the sound changes in phonetic notation (e.g. IPA). But you probably do most of the work for your languages in their romanization systems. Lexurgy has conventions for converting between IPA and romanizations so that you don't confuse romanization rules with actual sound changes.

If the input language has a romanization system, the first rule should be called deromanizer and contain all of the rules for converting from the input language's romanization to phonetic notation.

Ready
Input WordOutput Word

Similarly, if the output language has a romanization system, the last rule should be called romanizer and contain all of the rules for converting from phonetic language to the output language's romanization.

Ready
Input WordOutput Word

Intermediate Romanizers

If you want to preserve the history of the language at several stages, you can use intermediate romanizers. Any rule whose name starts with romanizer- will be treated as an intermediate romanizer.

Intermediate romanizers differ from ordinary rules in an important way: subsequent rules don't see the changes they make. Instead, their results are included in the output along with the final form of the word. Let's revisit the three-stage palatalization rule, but put in some intermediate romanizers:

Ready
Input WordOutput Word

Even though the romanizer-old-examplish rule changes all into ch, the following palatalization-2 rule still sees , as if the romanizer-old-examplish rule wasn't there.