Skip to content

Instantly share code, notes, and snippets.

@dginev
Created July 11, 2025 21:08
Show Gist options
  • Select an option

  • Save dginev/48645620f3a83f0252c671eeaedfb07d to your computer and use it in GitHub Desktop.

Select an option

Save dginev/48645620f3a83f0252c671eeaedfb07d to your computer and use it in GitHub Desktop.
[algorithm] computing the active property list in MathML Intent

Philosophy: "All properties apply, we need only define the order of precedence."

Note: this algorithm is executed before doing interpretation and vocalization of intent expressions. It linearizes a list of properties for each node in the MathML tree, as well as each term of compound intent expressions.

Legend:

  • self-property - attached to the node itself (intent=":matrix")
  • ref-property - attached to a reference (intent = "$ref:equation-label")
  • fragment-property - attached to a non-reference head in a compound expression
    • intent="factorial:function(2:literal)"
  • leaf-property - attached to a standalone concept, literal or number (intent="plus:prefix")

Idea:

  • self-properties are inherited by children, act as defaults (low precedence)
    • [FLAW] except when they aren't inherited. :matrix and :common have the same syntax but act very differently.
      • the group should have split these behaviors to have different syntax.
      • for now consider the self-properties that do NOT inherit to be leaf-properties in this Legend. (implementers would need to maintain a hardcoded list of exceptions)
  • ref-properties override the target node's properties, they have higher precedence.
  • leaf-properties - they only apply to the leaf carrying them
    • have higher precedence than ancestor self-properties (and inherit them)
    • can be overridden by ref-properties.
  • fragment-properties apply only to a fragment in a compound intent expression, otherwise same as leaf-properties

Algorithms in pseudocode:

Convention: A priority queue order is last-to-first, the first element has highest priority


function CurrentProperties(node-or-term):

Argument: 
 - A MathML node or intent term

Returns:
 - A priority queue of intent properties

Steps:
  1. the current node-or-term's property list is interpreted left-to-right, 
  2. right-most property having highest priority 
      - example:lower:higher will return [:lower,:higher]
      - <mo intent="example:lower:higher"> will return [:lower,:higher]
      - <mo intent="plus:function(2)"> will return []

function LinearizeProperties(P_default, P_override, node):

Arguments:
 - a priority queue P_default for ancestor property defaults (self-properties)
 - a priority queue P_override for ancestor property overrides (ref-properties)
 - a MathML node 
 
Returns:
 - nothing, written so as to bookkeep a global ComputedProperties for the tree 
   (or can annotate the nodes in place, etc)

Steps:

if (node is a leaf in the MathML tree, or carrying a leaf intent annotation):
   SET ComputedProperties{node} = appended(P_default, CurrentProperties(node), P_override)

else if (intent is one or more self-properties):
   P_inherit = appended(P_default, CurrentProperties(node), P_override) 
   SET ComputedProperties{node} = P_inherit
   recurse LinearizeProperties(P_inherit, [], child) for all children

else if (intent is a reference with properties)  
   P_inherit_override = appended(CurrentProperties(node), P_override)
   # no SET, this is a pass-through node
   recurse LinearizeProperties(P_default, P_inherit_override, ref_node) for referenced node only  
           
else if (intent is a compound expression)
   # Ignore overrides? Overrides on individual terms would be very confusing,
   #  lots of possible unintended consequences. This feels weird.
   
   SET ComputedProperties{term} = appended(P_default, CurrentProperties(term)) for each non-ref intent term
   recurse LinearizeProperties(P_default, [], ref_term) for each reference term 
        (reusing notation, terms are not nodes after all)

After the properties are linearized, the tree can be traversed again to interpret and vocalize

(this is similar to using Computed CSS to render HTML).

Gist context: see mathml#449

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment