Lexurgy Sound Changer Tutorial — Building Complex Rules
Simultaneous Expressions
Recall that Lexurgy applies rules one after the other, from top to bottom:
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:
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:
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:
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:
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:
This creates many sequences of vowels in hiatus. You may want to simplify these sequences by combining them according to a chart:
But what if there are several dropped consonants in a row?
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:
Controlling Propagation Direction
Propagation is very powerful, but sometimes you want propagation to go in one direction only. Take this example:
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:
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:
For propagation from the end of the word to the beginning, use the rtl
modifier:
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:
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:
Then you go on developing your language, and at some point you have a vowel deletion rule:
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:
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:
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:
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:
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.
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.
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:
Even though the romanizer-old-examplish
rule changes all tʃ
into ch
, the following palatalization-2
rule still sees tʃ
, as if the romanizer-old-examplish
rule wasn't there.