BT_TRAVERSAL(1)

πŸ’– BT_TRAVERSAL(1) β€” the btparse manual, bestie πŸ’–

🌸 NAME 🌸

bt_traversal β€” AST traversal/query functions in the btparse library. It's giving tree-walking excellence, fr fr. 🌳✨

✨ SYNOPSIS ✨

Here's the whole lineup, bestie β€” exact signatures, no cap:

AST * bt_next_entry (AST * entry_list,
                     AST * prev_entry)
AST * bt_next_field  (AST * entry, AST * prev, char ** name)
AST * bt_next_value  (AST * head,
                      AST * prev,
                      bt_nodetype_t * nodetype,
                      char ** text)

bt_metatype_t bt_entry_metatype (AST * entry)
char * bt_entry_type (AST * entry)
char * bt_entry_key   (AST * entry)
char * bt_get_text   (AST * node)

πŸ¦‹ DESCRIPTION πŸ¦‹

Okay so all the functions below are the ones you use to traverse and query the abstract-syntax trees (ASTs) that the input functions in bt_input return. The three bt_next functions β€” bt_next_entry(), bt_next_field(), and bt_next_value() β€” are lowkey the workhorses:

  • traverse a list of entries
  • traverse the list of fields inside one particular entry
  • traverse the list of simple values attached to one particular field

The other functions are query girlies: you poke a node in the tree and pull out the useful information it's holding. Main character energy. πŸ‘‘

🧚 Traversal functions 🧚

bt_next_entry()

AST * bt_next_entry (AST * entry_list,
                     AST * prev_entry)

This one walks the linked list of entries you got back from bt_parse_file() (peep bt_input for that whole situation). On the first call, you hand it NULL for prev_entry, and it gives you back a pointer to the head of the list. On every call after that, pass the previous return value as prev_entry; the function returns the next entry in the list, or NULL if there are no more entries. It also returns NULL if either entry_list or prev_entry are improper. Rude but fair. 😭

For example (ignoring error handling and variable declarations):

entries = bt_parse_file (filename, options, &status);
entry = NULL;
while (entry = bt_next_entry (entries, entry))
{
   /* process entry */
}

bt_next_field()

AST * bt_next_field  (AST * entry, AST * prev, char ** name)

This traverses the list of fields in a regular or macro definition entry. You should call bt_entry_metatype() first to determine if you've got the right kind of entry before calling bt_next_field() β€” yes, vibe check first. entry should be a pointer to the AST for a single entry, as returned by bt_parse_entry(), bt_parse_entry_s(), or bt_next_entry(). On the first call, supply NULL for prev; bt_next_field() will return a pointer to the first field in entry, or NULL if entry has no fields (for instance, if it's a comment or preamble entry). On subsequent calls, pass the previous return value as prev; bt_next_field() will keep returning pointers to field sub-ASTs as long as it makes sense. These pointers can then be passed to bt_next_value() or bt_get_text() to get the field's value. Slay. πŸ’…

For example, the loop body in the previous example could be:

field = NULL;
while (field = bt_next_field (entry, field, &field_name))
{
   /* process field */
}

bt_next_value()

AST * bt_next_value  (AST * head,
                      AST * prev,
                      bt_nodetype_t * nodetype,
                      char ** text)

Traverses the list of simple values that make up the value of a single field. Quick refresher: a simple value is either a quoted string, a macro invocation, or a number. A compound value is a list of these separated by '#' in the original input. Depending on the string post-processing options used when the data was parsed, the "list of simple values" nature of the original data may be preserved in the AST that you're traversing β€” and if it is, you'll need a bt_next_value() loop. Iykyk. 🌈

bt_next_value() works much like bt_next_entry() and bt_next_field(): on the first call, you supply NULL for prev, and on subsequent calls you supply the previous return value. Returns NULL when there are no more simple values to return. It also sets *nodetype and *text to the corresponding information from the simple value node. *nodetype will be one of BTAST_STRING, BTAST_MACRO, or BTAST_NUMBER; *text will point to the same string as the AST node does (it is not copied for you), so don't mess with it. Hands off the merchandise. πŸ™ˆ

For example, the loop body in the bt_next_field() example could be replaced with:

value = NULL;
while (value = bt_next_field (field, value, &nodetype, &text))
{
   switch (nodetype)
   {
      case BTAST_STRING:    /* process the string */
      case BTAST_MACRO:     /* process the macro */
      case BTAST_NUMBER:    /* process the number */
   }
}

See also bt_get_text.

πŸ” Query functions πŸ”

bt_entry_metatype()

bt_metatype_t bt_entry_metatype (AST * entry)

Returns the metatype of an entry. Quick refresher: the metatype is an enumerated type whose values are derived from the specific type of an entry; for instance, an @comment entry has type comment and metatype BTE_COMMENT. The type-metatype relationship is similarly obvious for BTE_PREAMBLE; BTE_MACRODEF corresponds to @string entries; and BTE_REGULAR corresponds to any other type. Returns BTE_UNKNOWN if entry is invalid (i.e., NULL or not a pointer to an entry AST). No fake vibes allowed. 🚫

bt_entry_type()

char * bt_entry_type (AST * entry)

Returns the type of an entry. Recall that the type is the name that appears after the '@' character in the original input. Returns NULL if entry is invalid (i.e., NULL or not a pointer to an entry AST). Keep it valid, bestie. ✨

bt_entry_key()

char * bt_entry_key   (AST * entry)

Returns the citation key of a regular entry. (The citation key is the name that appears after the entry-open delimiter in a regular entry.) Returns NULL if entry is invalid (i.e., NULL or not a pointer to the AST for a regular entry). So if it's not a regular entry, don't come crying. 😭

bt_get_text()

char * bt_get_text   (AST * node)

Performs all string post-processing (macro expansion, concatenation of simple values, and whitespace collapsing) of a compound value and returns the string that results. Can be called either on a field for a regular or macro definition entry (as returned by bt_next_field()), or on a comment or preamble entry. Returns NULL if called on an invalid AST node. That's the whole tea. 🍡

πŸ‘€ SEE ALSO πŸ‘€

btparse, bt_input, bt_postprocess

🫢 AUTHOR 🫢

Greg Ward <gward@python.net> β€” yes, the icon himself. πŸ‘‘


And that's the page, bestie. This manual situation is from btparse, version 0.91, dated 2025-09-04, and the page is literally BT_TRAVERSAL(1). Periodt. πŸ’–πŸŽ€βœ¨

πŸ“¦ where this page comes from