<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://sualex.cenzontle.org/index.php?action=history&amp;feed=atom&amp;title=Module%3Aparser</id>
	<title>Module:parser - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://sualex.cenzontle.org/index.php?action=history&amp;feed=atom&amp;title=Module%3Aparser"/>
	<link rel="alternate" type="text/html" href="https://sualex.cenzontle.org/index.php?title=Module:parser&amp;action=history"/>
	<updated>2026-04-20T01:41:18Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://sualex.cenzontle.org/index.php?title=Module:parser&amp;diff=1207&amp;oldid=prev</id>
		<title>Jawad at 14:26, 29 January 2026</title>
		<link rel="alternate" type="text/html" href="https://sualex.cenzontle.org/index.php?title=Module:parser&amp;diff=1207&amp;oldid=prev"/>
		<updated>2026-01-29T14:26:39Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://sualex.cenzontle.org/index.php?title=Module:parser&amp;amp;diff=1207&amp;amp;oldid=1205&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Jawad</name></author>
	</entry>
	<entry>
		<id>https://sualex.cenzontle.org/index.php?title=Module:parser&amp;diff=1205&amp;oldid=prev</id>
		<title>Jawad: Created page with &quot;-- Module:parser  local utilities = require(&quot;Module:utilities&quot;)  local parser = {}  function parser.parse_term(value)     if not value or value == &quot;&quot; then return {} end     local parts = utilities.split_string(value, &quot;:&quot;)     local term_item = parts[1] or &quot;&quot;     local display_form = parts[2]     -- capture whatever follows # as homonym (string), e.g. &quot;1&quot; for &quot;#1&quot;     local homonym = term_item:match(&quot;#(.+)$&quot;)     term_item = term_item:gsub(&quot;#.+$&quot;, &quot;&quot;)     return {term_ite...&quot;</title>
		<link rel="alternate" type="text/html" href="https://sualex.cenzontle.org/index.php?title=Module:parser&amp;diff=1205&amp;oldid=prev"/>
		<updated>2026-01-29T14:24:23Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;-- Module:parser  local utilities = require(&amp;quot;Module:utilities&amp;quot;)  local parser = {}  function parser.parse_term(value)     if not value or value == &amp;quot;&amp;quot; then return {} end     local parts = utilities.split_string(value, &amp;quot;:&amp;quot;)     local term_item = parts[1] or &amp;quot;&amp;quot;     local display_form = parts[2]     -- capture whatever follows # as homonym (string), e.g. &amp;quot;1&amp;quot; for &amp;quot;#1&amp;quot;     local homonym = term_item:match(&amp;quot;#(.+)$&amp;quot;)     term_item = term_item:gsub(&amp;quot;#.+$&amp;quot;, &amp;quot;&amp;quot;)     return {term_ite...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Module:parser&lt;br /&gt;
&lt;br /&gt;
local utilities = require(&amp;quot;Module:utilities&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
local parser = {}&lt;br /&gt;
&lt;br /&gt;
function parser.parse_term(value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then return {} end&lt;br /&gt;
    local parts = utilities.split_string(value, &amp;quot;:&amp;quot;)&lt;br /&gt;
    local term_item = parts[1] or &amp;quot;&amp;quot;&lt;br /&gt;
    local display_form = parts[2]&lt;br /&gt;
    -- capture whatever follows # as homonym (string), e.g. &amp;quot;1&amp;quot; for &amp;quot;#1&amp;quot;&lt;br /&gt;
    local homonym = term_item:match(&amp;quot;#(.+)$&amp;quot;)&lt;br /&gt;
    term_item = term_item:gsub(&amp;quot;#.+$&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    return {term_item = term_item, homonym = homonym, display_form = display_form}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parser.parse_spelling(value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then return {} end&lt;br /&gt;
    local parts = utilities.split_string(value, &amp;quot;:&amp;quot;)&lt;br /&gt;
    return {spelling_item = parts[1], orthography = parts[2]}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parser.parse_gloss(value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then return {} end&lt;br /&gt;
    -- capture trailing #... as sup (e.g. &amp;quot;?&amp;quot; from &amp;quot;#?&amp;quot;)&lt;br /&gt;
    local sup = value:match(&amp;quot;#(.+)$&amp;quot;)&lt;br /&gt;
    value = value:gsub(&amp;quot;#.+$&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    return {gloss_item = value, sup = sup}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parser.parse_reference(value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then return {} end&lt;br /&gt;
    local parts = utilities.split_string(value, &amp;quot;:&amp;quot;)&lt;br /&gt;
    return {author = parts[1], year = parts[2], page = parts[3]}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parser.parse_etymon(value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then return {} end&lt;br /&gt;
    value = utilities.trim_string(value)&lt;br /&gt;
    local colon_pos = value:find(&amp;quot;:&amp;quot;, 1, true)&lt;br /&gt;
    if not colon_pos then return {} end&lt;br /&gt;
    local descendant_type = utilities.trim_string(value:sub(1, colon_pos - 1))&lt;br /&gt;
    local global_uncertainty = descendant_type:match(&amp;quot;#?%?$&amp;quot;) and true or false&lt;br /&gt;
    descendant_type = descendant_type:gsub(&amp;quot;#?%?$&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
    local sub = value:sub(colon_pos + 1)&lt;br /&gt;
&lt;br /&gt;
    -- try to capture an initial language token at the start (e.g. &amp;quot;bew:&amp;quot;)&lt;br /&gt;
    local initial_lang = sub:match(&amp;quot;^([a-z%-]+):&amp;quot;)&lt;br /&gt;
    if initial_lang then&lt;br /&gt;
        sub = sub:gsub(&amp;quot;^&amp;quot; .. initial_lang:gsub(&amp;quot;%-&amp;quot;, &amp;quot;%%-&amp;quot;) .. &amp;quot;:&amp;quot;, &amp;quot;&amp;quot;, 1)&lt;br /&gt;
    else&lt;br /&gt;
        initial_lang = nil&lt;br /&gt;
    end&lt;br /&gt;
    sub = utilities.trim_string(sub)&lt;br /&gt;
&lt;br /&gt;
    -- split on &amp;#039;+&amp;#039; (items); preserve order&lt;br /&gt;
    local item_strings = {}&lt;br /&gt;
    for item in (sub .. &amp;quot;+&amp;quot;):gmatch(&amp;quot;(.-)%+&amp;quot;) do&lt;br /&gt;
        local trimmed = utilities.trim_string(item)&lt;br /&gt;
        if trimmed ~= &amp;quot;&amp;quot; then table.insert(item_strings, trimmed) end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local parsed_items = {}&lt;br /&gt;
    local current_lang = initial_lang&lt;br /&gt;
&lt;br /&gt;
    for _, raw_item in ipairs(item_strings) do&lt;br /&gt;
        local item_str = utilities.trim_string(raw_item)&lt;br /&gt;
&lt;br /&gt;
        -- handle optional leading &amp;quot;lang:&amp;quot; inside this item (overrides current_lang)&lt;br /&gt;
        local lang_match = item_str:match(&amp;quot;^([a-z%-]+):&amp;quot;)&lt;br /&gt;
        if lang_match then&lt;br /&gt;
            current_lang = lang_match&lt;br /&gt;
            item_str = item_str:gsub(&amp;quot;^&amp;quot; .. lang_match:gsub(&amp;quot;%-&amp;quot;, &amp;quot;%%-&amp;quot;) .. &amp;quot;:&amp;quot;, &amp;quot;&amp;quot;, 1)&lt;br /&gt;
        end&lt;br /&gt;
        if not current_lang then current_lang = &amp;quot;unknown&amp;quot; end&lt;br /&gt;
&lt;br /&gt;
        local sup = nil&lt;br /&gt;
        local homonym = nil&lt;br /&gt;
&lt;br /&gt;
        local last = item_str:match(&amp;quot;#([^#]+)$&amp;quot;)&lt;br /&gt;
        if last then&lt;br /&gt;
&lt;br /&gt;
            local before_last = item_str:sub(1, -(#last) - 2) -- remove &amp;#039;#&amp;#039; and last content&lt;br /&gt;
            local second = before_last:match(&amp;quot;#([^#]+)$&amp;quot;)&lt;br /&gt;
            if second then&lt;br /&gt;
                -- two hashes: second = homonym, last = sup&lt;br /&gt;
                homonym = second&lt;br /&gt;
                sup = last&lt;br /&gt;
                -- now remove the second &amp;#039;#...&amp;#039; from before_last to get base_and_rest&lt;br /&gt;
                item_str = before_last:sub(1, -(#second) - 2)&lt;br /&gt;
            else&lt;br /&gt;
                -- only one &amp;#039;#&amp;#039;: decide whether it&amp;#039;s homonym or sup&lt;br /&gt;
                if last == &amp;quot;?&amp;quot; then&lt;br /&gt;
                    sup = last&lt;br /&gt;
                    item_str = before_last -- base without final #?&lt;br /&gt;
                else&lt;br /&gt;
                    homonym = last&lt;br /&gt;
                    item_str = before_last -- base without final #N&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        item_str = utilities.trim_string(item_str)&lt;br /&gt;
&lt;br /&gt;
        local parts = utilities.split_string(item_str, &amp;quot;:&amp;quot;)&lt;br /&gt;
        local etym_item = parts[1] or &amp;quot;&amp;quot;&lt;br /&gt;
        local display_form = parts[2]&lt;br /&gt;
&lt;br /&gt;
        local leftover_homonym = etym_item:match(&amp;quot;#(.+)$&amp;quot;)&lt;br /&gt;
        if leftover_homonym and not homonym then&lt;br /&gt;
            homonym = leftover_homonym&lt;br /&gt;
        end&lt;br /&gt;
        etym_item = etym_item:gsub(&amp;quot;#.+$&amp;quot;, &amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        local parsed_item = {&lt;br /&gt;
            lang_code = current_lang,&lt;br /&gt;
            etymon_item = etym_item,&lt;br /&gt;
            homonym = homonym,&lt;br /&gt;
            display_form = display_form,&lt;br /&gt;
            sup = sup,  -- trailing superscript content (string), e.g. &amp;quot;?&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if sup == &amp;quot;?&amp;quot; then&lt;br /&gt;
            parsed_item.uncertainty = true&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        table.insert(parsed_items, parsed_item)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        descendant_type = descendant_type,&lt;br /&gt;
        initial_lang = initial_lang,&lt;br /&gt;
        uncertainty = global_uncertainty,&lt;br /&gt;
        items = parsed_items&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parser.parse_field(field_name, value)&lt;br /&gt;
    if not value or value == &amp;quot;&amp;quot; then return {} end&lt;br /&gt;
    local parsers = {&lt;br /&gt;
        term = parser.parse_term,&lt;br /&gt;
        spelling = parser.parse_spelling,&lt;br /&gt;
        gloss = parser.parse_gloss,&lt;br /&gt;
        reference = parser.parse_reference,&lt;br /&gt;
        etymon = parser.parse_etymon,&lt;br /&gt;
    }&lt;br /&gt;
    local parser_fn = parsers[field_name]&lt;br /&gt;
    return parser_fn and parser_fn(value) or {raw = value}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function parser.parse_entry(entry, lang_code)&lt;br /&gt;
    local fields = {&amp;quot;term&amp;quot;, &amp;quot;spelling&amp;quot;, &amp;quot;gloss&amp;quot;, &amp;quot;reference&amp;quot;, &amp;quot;etymon&amp;quot;, &amp;quot;notes&amp;quot;}&lt;br /&gt;
    local parsed = {lang_code = lang_code}&lt;br /&gt;
    for i, field in ipairs(fields) do&lt;br /&gt;
        local raw = entry[i] or &amp;quot;&amp;quot;&lt;br /&gt;
        local sep = require(&amp;quot;Module:parameters&amp;quot;).value_separator or &amp;quot;\\&amp;quot;&lt;br /&gt;
        local values = utilities.split_string(raw, sep)&lt;br /&gt;
        parsed[field] = {}&lt;br /&gt;
        for _, val in ipairs(values) do&lt;br /&gt;
            table.insert(parsed[field], parser.parse_field(field, utilities.trim_string(val)))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return parsed&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return parser&lt;/div&gt;</summary>
		<author><name>Jawad</name></author>
	</entry>
</feed>