<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://yezur.xyz/w/index.php?action=history&amp;feed=atom&amp;title=Module%3AAuphen%2Fdoc</id>
	<title>Module:Auphen/doc - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://yezur.xyz/w/index.php?action=history&amp;feed=atom&amp;title=Module%3AAuphen%2Fdoc"/>
	<link rel="alternate" type="text/html" href="https://yezur.xyz/w/index.php?title=Module:Auphen/doc&amp;action=history"/>
	<updated>2026-08-28T16:49:31Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://yezur.xyz/w/index.php?title=Module:Auphen/doc&amp;diff=13112&amp;oldid=prev</id>
		<title>Thiorosan: Create the documentation subpage</title>
		<link rel="alternate" type="text/html" href="https://yezur.xyz/w/index.php?title=Module:Auphen/doc&amp;diff=13112&amp;oldid=prev"/>
		<updated>2026-08-27T12:19:34Z</updated>

		<summary type="html">&lt;p&gt;Create the documentation subpage&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This is the documentation for [[Module:Auphen]], the sound-change engine for the Yezur wiki. It applies an ordered ruleset of rewrite rules to a word and returns the result. It exports no &amp;lt;code&amp;gt;#invoke&amp;lt;/code&amp;gt; entry point and is not called from wikitext: [[Module:Auphen/frame]] requires it, hands it the data for one language and backs [[Template:Auphen]], so that &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{auphen|word|code}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; estimates a pronunciation and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{auphen|word|code|ruleset}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; runs a named ruleset. The categories, the glyph-to-sound table and the rulesets themselves are pure data on the &amp;lt;code&amp;gt;Module:Auphen/&amp;amp;lt;code&amp;amp;gt;&amp;lt;/code&amp;gt; pages; the engine holds no language-specific material. The rule notation is a port of PhoMo&amp;#039;s; the behaviour log, the divergences from it and the module&amp;#039;s provenance are kept on [[Module talk:Auphen]].&lt;br /&gt;
&lt;br /&gt;
== Interface ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Call !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Auphen.new(categories, ipa_rules, opts)&amp;lt;/code&amp;gt; || Builds an engine. &amp;lt;code&amp;gt;categories&amp;lt;/code&amp;gt; maps each bracketed category name to an array of its members in declaration order; &amp;lt;code&amp;gt;ipa_rules&amp;lt;/code&amp;gt; is the glyph-to-sound table as a string; &amp;lt;code&amp;gt;opts&amp;lt;/code&amp;gt; holds the two settings below. Every argument may be omitted, and an engine built without &amp;lt;code&amp;gt;ipa_rules&amp;lt;/code&amp;gt; does no glyph conversion.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;eng:run(ruleset, input, toIpa)&amp;lt;/code&amp;gt; || Runs &amp;lt;code&amp;gt;ruleset&amp;lt;/code&amp;gt; over &amp;lt;code&amp;gt;input&amp;lt;/code&amp;gt; and returns the finished string. The input is split on spaces and on &amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt;, each part is processed as its own word with its own word edges, and the parts are rejoined with spaces. With &amp;lt;code&amp;gt;toIpa&amp;lt;/code&amp;gt; true the input is first lower-cased, sentence-final punctuation and the colon become &amp;lt;code&amp;gt;&amp;amp;#124;&amp;lt;/code&amp;gt;, other punctuation is dropped, and &amp;lt;code&amp;gt;ipa_rules&amp;lt;/code&amp;gt; is applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;eng:run_word(ruleset, word)&amp;lt;/code&amp;gt; || Runs the ruleset over a single word. Returns the finished word and a trace holding, for each rule, its text, the word after it and whether it applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;eng.warnings&amp;lt;/code&amp;gt; || Warnings gathered while loading and running: an invalid category name, a category reference that cannot be resolved, an affix category used without an index, an affix index that matches nothing, a rule skipped for exceeding the cap below. [[Module:Auphen/frame]] does not read them.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;opts.explodeCap&amp;lt;/code&amp;gt; || The ceiling on the number of variants one segment of a rule may expand to, 5,000,000 by default. A segment above it expands to nothing and the rule is skipped with a warning rather than left to exhaust the parser.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;opts.dashToSpace&amp;lt;/code&amp;gt; || When true, hyphens in the finished word become spaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Neither option is reachable from wikitext: [[Module:Auphen/frame]] builds the engine without an &amp;lt;code&amp;gt;opts&amp;lt;/code&amp;gt; table, so template calls run at the default cap and leave hyphens untouched.&lt;br /&gt;
&lt;br /&gt;
== Rule lines ==&lt;br /&gt;
&lt;br /&gt;
A ruleset is plain text, one rule to a line; a line containing no &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; is ignored. Each rule has up to five fields, separated by &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 target / change / environment / exception / else&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| target || What the rule matches. &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; alone means the whole word; an empty target matches at every slot from before the first character to after the last.&lt;br /&gt;
|-&lt;br /&gt;
| change || What the match becomes. An empty field deletes it.&lt;br /&gt;
|-&lt;br /&gt;
| environment || Conditions on the surrounding word; the rule applies only where one of them holds. An empty field imposes no condition.&lt;br /&gt;
|-&lt;br /&gt;
| exception || Conditions written the same way; where one holds, the rule is blocked.&lt;br /&gt;
|-&lt;br /&gt;
| else || Applied in place of the change wherever the environment fails or an exception holds. An empty field leaves the match alone.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Rules run in order, each on the output of the last. The word is lower-cased before a rule sees it, and the finished word is re-cased to match the input: all lower, all upper, or otherwise capitalised. A rule whose target is &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; and whose change contains &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt; is treated as an affixation instead of a replacement; such a rule has no target position, so a condition containing &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt; never holds in one.&lt;br /&gt;
&lt;br /&gt;
== Notation ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Notation !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[X]&amp;lt;/code&amp;gt; || A category: a bracketed capital followed by up to two more letters, its members listed on the language&amp;#039;s data page. Members are tried longest first when matching but map by position, so the &amp;#039;&amp;#039;n&amp;#039;&amp;#039;th member of the target&amp;#039;s category becomes the &amp;#039;&amp;#039;n&amp;#039;&amp;#039;th member of the change&amp;#039;s.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[a,b,c]&amp;lt;/code&amp;gt; || A category written in place, members comma-separated, without being declared.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; || In the change, the text that was matched, so that &amp;lt;code&amp;gt;%%&amp;lt;/code&amp;gt; doubles it; where the target is &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; it is the whole word. In a condition, replaced by the matched text before the condition is tested.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; || The matched text reversed, or the whole word where the target is &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt;; it is read the same way in a condition. As the whole change, &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039; reverses that text from position &amp;#039;&amp;#039;n&amp;#039;&amp;#039;, counting from the end where &amp;#039;&amp;#039;n&amp;#039;&amp;#039; is negative, and &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039;&amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;m&amp;#039;&amp;#039; reverses &amp;#039;&amp;#039;m&amp;#039;&amp;#039; characters from there.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt; || The target&amp;#039;s own slot, which makes the condition local: what stands left of &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt; must precede the match and what stands right of it must follow. A condition without &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt; is global and is tested against the whole word.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt; || In a local condition, separates material that need not be adjacent: the segment nearest the slot must abut it, the others need only occur in order further out.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; || A word edge. The word is padded with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; at each end, so a local condition tests an edge in place; in a global condition, material before the &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; must be word-initial and material after it word-final.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt; || Counts occurrences, without overlap, in a global condition. &amp;lt;code&amp;gt;[V]=3&amp;lt;/code&amp;gt; holds at exactly three, &amp;lt;code&amp;gt;[V]=&amp;amp;gt;3&amp;lt;/code&amp;gt; at three or more, &amp;lt;code&amp;gt;[V]=&amp;amp;lt;3&amp;lt;/code&amp;gt; at three or fewer.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;amp;#124;&amp;lt;/code&amp;gt; || Separates alternative conditions; the field holds if any one of them does.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;&amp;lt;/code&amp;gt; || As a condition on its own, holds when the previous rule applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039; || Written at the end of the change, selects a single instance: the &amp;#039;&amp;#039;n&amp;#039;&amp;#039;th match of the target, counted from the end where &amp;#039;&amp;#039;n&amp;#039;&amp;#039; is negative. Instances are numbered by a left-to-right, longest-first scan, so overlapping members of one category count once. An index on the else field is used where the change carries none.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;m&amp;#039;&amp;#039; || After an index, the number of characters the change covers, counted from the start of the match rather than taken from the length of the target.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;x&amp;#039;&amp;#039; || Makes the operator character &amp;#039;&amp;#039;x&amp;#039;&amp;#039; an ordinary literal. The &amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt; of the movement marker &amp;lt;code&amp;gt;&amp;amp;gt;!&amp;lt;/code&amp;gt; is not read as an escape.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt; || A word boundary: each side is run as its own word and the output shows a space. A &amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt; produced by a rule becomes a plain space.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Affixation and movement ==&lt;br /&gt;
&lt;br /&gt;
In an affixation rule the change is a template in which &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; stands for the word; positions are counted in characters from 1, and a negative position counts from the end. Apart from the movement forms, a template with no &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; in it leaves the word unchanged; an index and span with no material at all delete. Category references and &amp;lt;code&amp;gt;##&amp;lt;/code&amp;gt; are resolved before the template is applied, and &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; are not read here.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Change !! Effect&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;x#&amp;lt;/code&amp;gt; || Prefixes &amp;#039;&amp;#039;x&amp;#039;&amp;#039;; &amp;lt;code&amp;gt;#x&amp;lt;/code&amp;gt; suffixes it and &amp;lt;code&amp;gt;x#y&amp;lt;/code&amp;gt; circumfixes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;##&amp;lt;/code&amp;gt; || Appends a copy of the word, each further &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; appending another. With an index the copy is that slice of the word — &amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;m&amp;#039;&amp;#039; giving its length, one character by default — and is placed directly after it.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;#x@&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039; || Inserts &amp;#039;&amp;#039;x&amp;#039;&amp;#039; after character &amp;#039;&amp;#039;n&amp;#039;&amp;#039;; &amp;lt;code&amp;gt;x#@&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039; inserts it before.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;x#@&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039;&amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;m&amp;#039;&amp;#039; || Replaces &amp;#039;&amp;#039;m&amp;#039;&amp;#039; characters from position &amp;#039;&amp;#039;n&amp;#039;&amp;#039; with &amp;#039;&amp;#039;x&amp;#039;&amp;#039;, or deletes them where the material is empty.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;#[X]@&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;n&amp;#039;&amp;#039; || The &amp;#039;&amp;#039;n&amp;#039;&amp;#039;th member of category X occurring in the word, used as affix material and here suffixed. The index is consumed by the category, so the template&amp;#039;s &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; alone places the material.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;s&amp;#039;&amp;#039;&amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;d&amp;#039;&amp;#039;&amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;m&amp;#039;&amp;#039; || Moves &amp;#039;&amp;#039;m&amp;#039;&amp;#039; characters, one by default, from position &amp;#039;&amp;#039;s&amp;#039;&amp;#039; to position &amp;#039;&amp;#039;d&amp;#039;&amp;#039;, the destination being counted in the word with the block already removed. &amp;lt;code&amp;gt;&amp;amp;gt;!&amp;lt;/code&amp;gt; in place of &amp;lt;code&amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt; copies the block instead, counting the destination in the unchanged word.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Notes ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ipa_rules&amp;lt;/code&amp;gt; is read as one &amp;lt;code&amp;gt;glyph/sound&amp;lt;/code&amp;gt; pair per line, longest glyph first; anything it does not match passes through unchanged. It is applied only on the pronunciation path, where [[Module:Auphen/frame]] runs the data page&amp;#039;s &amp;lt;code&amp;gt;pronounce&amp;lt;/code&amp;gt; ruleset against its &amp;lt;code&amp;gt;ipacats&amp;lt;/code&amp;gt; categories and wraps the result in slashes. A named ruleset is taken from &amp;lt;code&amp;gt;sets&amp;lt;/code&amp;gt; and run against &amp;lt;code&amp;gt;cats&amp;lt;/code&amp;gt;, over the orthography and with no glyph conversion. Either category set stands in for the other where a data page defines only one.&lt;br /&gt;
&lt;br /&gt;
Worked examples for the languages with sound data are on [[Template:Auphen/testcases]], which calls &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{#invoke:Auphen/frame|raw}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for unformatted output. A missing word or code, a code with no data page and an unknown ruleset are reported rather than raised: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{auphen}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; renders the message as an error and files the page in [[:Category:Auphen errors]], while &amp;lt;code&amp;gt;raw&amp;lt;/code&amp;gt; returns it as a plain &amp;lt;code&amp;gt;ERROR:&amp;lt;/code&amp;gt; line.&lt;/div&gt;</summary>
		<author><name>Thiorosan</name></author>
	</entry>
</feed>