> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/ru/podrobnye-stati/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md).

# Как работает \\\expandafter: от основных принципов к изучению исходного кода TeX

[Часть 1](/latex/ru/podrobnye-stati/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md) [Часть 2](/latex/ru/podrobnye-stati/22-how-does-expandafter-work-the-meaning-of-expansion.md) [Часть 3](/latex/ru/podrobnye-stati/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) [Часть 4](/latex/ru/podrobnye-stati/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md) [Часть 5](/latex/ru/podrobnye-stati/17-how-does-expandafter-work-a-detailed-macro-case-study.md) [Часть 6](/latex/ru/podrobnye-stati/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)

## Введение

Теперь мы рассмотрели фоновые темы, необходимые для полного изучения `\expandafter`:

* основ TeX-токенов и того, как они вычисляются;
* принципов, лежащих в основе процесса расширения TeX;
* использования/создания TeX временных списков токенов во время обработки документа;
* того, как TeX использует и «жонглирует» несколькими источниками ввода (включая временные списки токенов).

В этой статье мы соберём эти темы/понятия вместе, чтобы объяснить механизмы, лежащие в основе `\expandafter` команды TeX: вкратце, как она работает.

## Итак, к \expandafter

Идея, стоящая за `\expandafter` заключается в том, чтобы принудительно расширить команду (токен) раньше, чем TeX сделал бы это обычно. Даны два токена, $$\mathrm{T\_1}$$ и $$\mathrm{T\_2}$$ действие `\expandafter` $$\mathrm{T\_1T\_2}$$ приводит к тому, что TeX обрабатывает $$\mathrm{T\_1}\text{<}$$расширение $$\mathrm{T\_2}\text{>}$$, где $$\text{<}\dots\text{>}$$ обозначает список токенов. TeX расширяет $$\mathrm{T\_2}$$ заранее, чтобы токен $$\mathrm{T\_1}$$ (например, примитив или макрос) смог увидеть токены, возникающие в результате расширения $$\mathrm{T\_2}$$. Если токен $$\mathrm{T\_2}$$ представляет нерасширяемый элемент, такой как неактивный символ или (большинство) примитивов, действие `\expandafter` ничего не меняет: TeX продолжил бы обрабатывать токены $$\mathrm{T\_1T\_2}$$ обычным образом.

### Введение в использование \expandafter

Если вы не использовали `\expandafter`, вот пример его использования с примитивом `\uppercase{...}`. Допустим, мы хотим набрать имя нашего основного `.tex` входного файла, но заглавными буквами. Мы могли бы знать следующие примитивные команды TeX:

* `\uppercase`: делает то, что и следует из названия, преобразует символьные токены в их эквиваленты в верхнем регистре (если такие существуют);
* `\jobname`: как мы уже видели, расширяется, давая имя основного `.tex` файле.

Предположим, наш файл TeX называется `mycode.tex` мы могли бы разумно ожидать `\uppercase{\jobname}` чтобы было набрано `MYCODE`. Но нет, набирается `mycode` как в нижнем регистре. Что пошло «не так»?

Если мы запишем общее использование `\uppercase` как

```
\uppercase{<token list>}
```

мы можем сказать, что `\uppercase` просматривает `<token list>` и будет действовать (менять регистр) только на *символьные токены* которые он обнаруживает внутри `<token list>`: все несимвольные токены *игнорируются* потому что `\uppercase` не будет «заглядывать внутрь» (расширять) несимвольные токены, чтобы увидеть, что они содержат или представляют. Поскольку токен — это просто целочисленное значение, всё, что `\uppercase` нужно сделать, — это просмотреть список токенов и проверить, попадает ли числовое значение каждого токена в `<token list>` в диапазон значений, обозначающих символьный токен. Кстати, `\uppercase` также будет *менять регистр активных символов* создавая активный символ верхнего регистра, который, поскольку он по-прежнему активен, также должен быть определён, иначе TeX выдаст ошибку: `Неопределённая управляющая последовательность`, но мы отвлеклись...

Например, даже если мы определим макрос, который представляет собой просто текст

```
\def\foo{some lower-case text}
```

то `\uppercase{\foo}` всё равно набирает `some lower-case text` а не `SOME LOWER-CASE TEXT` как мы бы надеялись, просто потому что действие `\uppercase` не пытается определить, что `\foo` обозначает: он видит `\foo` как токен команды и игнорирует его, как и `\jobname`.

### Как это исправить? \expandafter приходит на помощь

Чтобы набрать имя файла в верхнем регистре, нам нужно изменить `\uppercase{\jobname}` путём принудительной замены `\jobname` его расширением (последовательностью символьных токенов) *до того, как* `\uppercase` начнёт работать. Ещё раз, расширение используется, чтобы удалить `\jobname` токен (команду) и заменить его результатом его расширения (списком токенов, содержащим символьные токены). Итак, если мы запишем

```
\uppercase\expandafter{\jobname}
```

то это работает: `MYCODE` будет набрано. Происходит следующее: TeX начинает обрабатывать `\uppercase` и сразу проверяет обязательный символ открывающей фигурной скобки (`{`); однако TeX обнаруживает `\expandafter` команду, из-за которой он временно «переключает внимание» на обработку `\expandafter{\jobname}`.

Если мы сравним

`\expandafter` $$\mathrm{T\_1T\_2}$$

с нашим примером

`\expandafter{\jobname}`

мы увидим

* $$\mathrm{T\_1} =\space$$`{`<sub>токен</sub>
* $$\mathrm{T\_2} =\space$$`\jobname`<sub>токен</sub>

Где `{`<sub>токен</sub> и `\jobname`<sub>токен</sub> относятся к значениям токенов, вычисляемым TeX — нижний индекс <sub>токен</sub> используется, чтобы напомнить себе, что TeX работает в мире целочисленных токенов.

Запись `\uppercase\expandafter{\jobname}` работает потому, что, в общих чертах (подробности далее), `\expandafter` заставляет TeX выполнить следующие задачи:

1. прочитать и сохранить открывающую `{`<sub>токен</sub>;
2. прочитать следующий токен: `\jobname`<sub>токен</sub>. TeX распознаёт, что `\jobname`<sub>токен</sub> представляет расширяемую команду, и расширяет её. `\jobname`<sub>токен</sub> заменяется своим расширением — серией символьных токенов;
3. после расширения `\jobname` команды TeX помещает `{`$$\_\mathrm{token}$$ «обратно во ввод» и использует список токенов, возникший в результате расширения `\jobname` так что TeX прочитает `\uppercase{`<sub>токен</sub>`<expansion of \jobname>`<sub>список токенов (символы)</sub>`}`, и это даёт нужный нам результат.

Следующая диаграмма показывает, как TeX обрабатывает `\uppercase\expandafter{\jobname}`— читайте схему снизу вверх, чтобы проследить поток процесса.

![Как работает \expandafter](/files/70ec4efa96778439e7a0e5343f742f31929a95de)

Следующие примечания объясняют различные этапы обработки.

1. TeX начинает обрабатывать `\uppercase` и проверяет обязательный символ открывающей фигурной скобки (`{`) но обнаруживает `\expandafter` команду.
2. Если мы сравним `\expandafter` $$\mathrm{T\_1T\_2}$$ к нашему вводу `\expandafter{\jobname}` мы увидим $$\mathrm{T\_1} =$$`{`<sub>токен</sub> и $$\mathrm{T\_2} =$$`\jobname`<sub>токен</sub>. Обратите внимание, что здесь мы будем использовать нижний индекс <sub>токен</sub> чтобы указать, что TeX обрабатывает целочисленные значения токенов.
3. `\expandafter` читает, затем временно сохраняет `{`<sub>токен</sub> путём сохранения этого целочисленного значения токена во внутренней переменной. Позже TeX снова вставит этот токен обратно во ввод после обработки `\jobname` команду.
4. `\expandafter` читает следующий токен, `\jobname`<sub>токен</sub>, и расширяет `\jobname` команду.
5. Расширение `\jobname` создаёт временный список токенов, который содержит последовательность символьных токенов, представляющих `.tex` имя файла. Обратите внимание, что все символьные токены, создаваемые `\jobname` вычисляются с использованием кода категории 12.
6. Как только `\jobname` будет расширен, TeX снова вставляет токен, сохранённый на шаге 3 (`{`<sub>токен</sub>) и помещает его обратно во ввод. TeX делает это, создавая ещё один список токенов, содержащий *один* `{`<sub>токен</sub>
7. TeX теперь завершил обработку `\expandafter`, в результате чего появились два списка токенов, готовые к использованию в качестве источников ввода TeX. Теперь TeX возвращается к обработке `\uppercase` но настроил свой ввод так, что два списка токенов, созданные `\expandafter` становятся источником токенов для `\uppercase`—который теперь видит `\uppercase{`<sub>токен</sub>`<expansion of \jobname>`<sub>список токенов (символы)</sub>`}`. `\uppercase` теперь видит последовательность символьных токенов и может выдать нужный нам результат.
8. После чтения всех символьных токенов, созданных `\jobname`, TeX возвращается к получению токенов из своего предыдущего источника ввода (нашего `.tex` файла), откуда он прочитает следующий токен: закрывающую `}` требуемую для завершения списка токенов, обрабатываемых `\uppercase`.

### \expandafter и внутренние списки токенов

Временные списки токенов — это *жизненно важный* элемент `\expandafter`поведения обработки TeX: понимание использования и существования этих списков токенов может помочь прояснить, как `\expandafter` достигает своих результатов, особенно при попытке писать или понимать макросы, которые используют несколько последовательных `\expandafter` команд для реализации более сложных форм обработки токенов: `\expandafter\expandafter\expandafter...`

Ещё один ключевой элемент `\expandafter`поведения, особенно при нескольких последовательных `\expandafter` командах, — это использование *рекурсии* (внутри самого ПО TeX) — темы, которую мы рассмотрим позже в этой статье.

Чтобы лучше понять временные списки токенов, мы рассмотрим ещё один пример `\expandafter`, на этот раз с `\the` команду.

#### \expandafter и внутренние списки токенов: пример 2

В этом примере мы увидим, как `\expandafter` можно использовать для влияния на токены, хранящиеся в регистре токенов, через команду `\toks` Вот примитивы TeX, которые мы будем использовать:

* `**\count** *register*=*number*`: примитив TeX, используемый для хранения значения `*number*` в ячейке TeX `*register*`;
* `**\toks** *register*={*token list*}`: примитив TeX, используемый для сохранения `*token list*` в ячейку регистра токенов `*register*`—сохраняя последовательность токенов для последующего использования;
* `**\the** *token*`: расширяемая примитивная команда TeX, которая обрабатывает `*token*`, хотя точные результаты зависят от природы `*token*` обрабатываемого. `\the` имеет ряд применений: среди них — вывод значения, хранящегося в параметре или переменной TeX (например, в регистре). Другие применения `\the` включают вставку копии токенов, хранящихся в регистре токенов. Здесь мы будем использовать `\the` для набора значения, хранящегося в `\count` регистре.

Начнём со следующего кода TeX, чтобы сохранить значение `12345` в `\count` регистре TeX `99`:

```
\count99=12345
```

Если мы хотим набрать значение, хранящееся в `\count99` мы можем использовать `\the\count99` (или `\number\count99`).

Далее мы используем `\toks` команду для сохранения некоторых токенов в регистре токенов `99`:

```
\toks99={\the\count99 }
```

Список токенов, сохранённый в регистре токенов `99` будет содержать следующее:

|                         |                                                                                                                             |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Значение токена TeX** | **Представляемый элемент**                                                                                                  |
| 5382                    | `\the`                                                                                                                      |
| 7885                    | `\count`                                                                                                                    |
| 3129                    | `9` (код символа 57 с кодом категории 12), в результате чего получается значение токена $$256 \times 12 + 57 = 3129$$       |
| 3129                    | `9` (код символа 57 с кодом категории 12), в результате чего получается значение токена $$256 \times 12 + 57 = 3129$$       |
| 2592                    | `<space>` (код символа 32 с кодом категории 10), в результате чего получается значение токена $$256 \times 10 + 32 = 2592$$ |

Обратите внимание, что список токенов, созданный `\toks99` не *не* содержит фактическое значение данных, хранящееся в `\count99` потому что `\toks` команда не выполняет расширение: она просто создаёт токены и сохраняет их. В нашем примере, `\the` не расширяется, поэтому она не обрабатывает `\count99`; здесь `\the` просто преобразуется в токен (значение 5382) и сохраняется в списке токенов.

Если мы хотим, чтобы `\toks99` список токенов содержал токены, представляющие данные, хранящиеся в `\count99` нам понадобится какой-то способ создать эти токены (сделать их доступными), чтобы `\toks` команда могла получить к ним доступ. И, конечно же, `\expandafter` может сделать это за нас. Если мы запишем:

```
        \toks99=\expandafter{\the\count99 }
```

действие/обработка `\toks` команды будут «приостановлены», в то время как `\expandafter` вызывает (принудительно) расширение `\the` которое, в свою очередь, действует на `\count` чтобы сгенерировать временный список токенов, содержащий символьные токены, представляющие данные, хранящиеся в `\count99`. Небольшой, но важный момент — это `<space>` символ после цифр `99`: этот `<space>` символ служит для завершения процесса разбора TeX, когда он ищет числовую величину.

Здесь действие `\expandafter` очень похоже на пример `\jobname` .

1. Прочитать и сохранить открывающую `{`<sub>токен</sub>.
2. Прочитать следующий токен, `\the`<sub>токен</sub>, который представляет расширяемую команду, поэтому TeX расширяет его. `\expandafter` принудительно расширяет `\the` которое затем действует на `\count99` чтобы преобразовать данные, хранящиеся в `\count` регистре TeX `99` (число 12345) во временный список токенов. Этот список будет содержать символьные токены, представляющие цифры `1`, `2`, `3`, `4` и `5`—символьные токены с кодом категории 12.
3. После расширения и обработки `\the`, TeX помещает `{`<sub>токен</sub> «обратно во ввод» и использует список токенов, возникающий из `\the\count99` так что TeX прочитает `\toks99={`<sub>токен</sub>`<expansion of \the\count99>`<sub>список токенов (символы)</sub>`}` и это даёт нужный нам результат.

Эта последовательность событий подытожена на следующей диаграмме — читайте схему снизу вверх, чтобы проследить поток процесса.

![Как работает \expandafter](/files/2f7378b8afd497d51cb09862a881b5d9cd4aa76a)

1. TeX начинает обрабатывать `\toks`; он видит необязательный `=` знак, затем проверяет обязательный символ открывающей фигурной скобки (`{`, или любой символ с кодом категории 1), используемый для обозначения начала списка токенов. Однако TeX обнаруживает `\expandafter` команду и вместо этого выполняет её.
2. Если мы сравним `\expandafter` $$\mathrm{T\_1T\_2}$$ к нашему вводу `\expandafter{\the\count99 }` мы увидим $$\mathrm{T\_1} =$$ `{`<sub>токен</sub> и $$\mathrm{T\_2} =$$ `\the<sub>token</sub>`.
3. `\expandafter` читает, затем временно сохраняет `{`<sub>токен</sub> (TeX временно сохраняет это целочисленное значение токена во внутренней переменной). Позже TeX снова вставит этот токен обратно во ввод после обработки `\the`
4. `\expandafter` читает следующий токен, `\the`<sub>токен</sub> и расширяет его.
5. Расширение `\the` создаёт временный список токенов, полученный при обработке `\count99`—этот список токенов содержит последовательность символьных токенов, которые представляют значение данных, хранящееся в `\count` регистре TeX `99`.
6. Как только `\the` будет расширен, TeX снова вставляет токен, сохранённый на шаге 3 (`{`<sub>токен</sub>) и помещает этот токен обратно во ввод. TeX делает это, создавая ещё один список токенов, содержащий *один* токен `{`<sub>токен</sub>.
7. TeX теперь завершил обработку `\expandafter` и создаёт два списка токенов, готовые быть использованными в качестве следующих источников ввода. TeX возвращается к обработке `\toks99=` но теперь TeX настроил свой ввод так, что два списка токенов, созданные `\expandafter` становятся источником токенов для `\toks`—который теперь видит `{`<sub>токен</sub>`<expansion of \the\count99>`<sub>список токенов (символы)</sub>`}`. `\toks` теперь может получить доступ и сохранить последовательность из 5 символьных токенов, которые представляют значение данных (`12345`) хранящееся в `\count99`: наш желаемый результат.
8. После чтения всех символьных токенов, созданных `\the\count99`, TeX возвращается к получению токенов из своего предыдущего источника ввода (нашего `.tex` файла), откуда он прочитает следующий токен: закрывающую `}` требуемого для завершения списка токенов, который должен быть сохранён `\toks99={...}`.

## Как \expandafter на самом деле работает

В этом разделе мы заглянем «на низкий уровень» внутрь самого TeX: исследуем исходный код/функции внутри TeX, которые реализуют поведение `\expandafter`. Подробности выражены в псевдо-C-коде, но будут понятны каждому, кто знаком с другими языками программирования.

Следующая аннотированная диаграмма объясняет, как TeX реализует `\expandafter` как часть более крупной функции под названием `expand()`—основной функции, которая управляет процессом расширения TeX. В разделе, отвечающем за реализацию `\expandafter` мы увидим [*рекурсивного* поведения](https://en.wikipedia.org/wiki/Recursion) когда ещё один вызов `expand()` функции используется для обработки второго прочитанного токена, $$\mathrm{T\_2}$$, для тех случаев, когда $$\mathrm{T\_2}$$ расширяем.

Хотя этот код присутствует в движке TeX Кнута, основные принципы, показанные на этой схеме, применимы ко всем движкам TeX.

![Как \expandafter работает внутри TeX](/files/136378feeae0075de009aa7d091beed8e0d59b58)

Первая задача `expand()` заключается в определении, является ли команда, подлежащая расширению, макросом или примитивом, поскольку у макросов есть специализированный процесс расширения, который обрабатывается функцией под названием `macrocall()`.

Если команда, подлежащая расширению, является примитивом, `expand()` функция использует текущее значение кода команды (хранящееся в глобальной переменной `curcmd`) для определения, какой именно примитив нужно обработать. Эти детали можно увидеть в более полном фрагменте `expand()`:

```
    void expand(void)
    {
    //curcmd — глобальная переменная
    if(curcmd != macro) // curcmd < 111
    {
      switch(curcmd)
      {
        case \expandafter: // Обработка команды \expandafter T1T2
        {
            gettoken(); // Считать токен T1
            t = curtok; // Сохранить токен T1 в локальной переменной t
            gettoken(); // Считать токен T2
            if(curcmd > 100) // Расширяем ли токен T2?
                expand();    // Да! Токен T2 расширяем:
                             // выполнить расширение T2 путем
                             // рекурсивного вызова функции expand()
            else
                backinput(); // T2 не расширяем: поместить этот токен
                             // обратно во входные данные, чтобы прочитать снова (позже)

            curtok = t ;  // Восстановить глобальную переменную curtok к сохраненному значению T1
            backinput() ; // Поместить токен T1 обратно во входные данные
                          // перед токенами, возникающими при расширении T2
        }
        break;

        // Код для обработки других расширяемых команд
        case «команда преобразования в текст»: // Любая из \number, \string, \romannumeral,
                                        // \meaning, \fontname, \jobname
                                        // У них общее значение curcmd
        break;

        case \noexpand: // Подавить расширение следующего токена
        ...
        break;

        case \csname:  // Сформировать имя управляющей последовательности.
        ...
        break;

        case \the: // Вставить несколько токенов
        ....
        break;

        case «\if... команда проверки»: // Обработать один из условных операторов TeX:
                                      // \if, \ifcat, \ifnum, \ifdim,\ifodd, \ifvmode,
                                      // \ifhmode, \ifmmode, \ifinner, \ifvoid,
                                      // \ifhbox, \ifvbox, \ifx, \ifeof, \iftrue, \iffalse,
                                      // \ifcase, \ifdefined, \ifcsname, \iffontchar
        ...
        break;

        case “\fi or \else”: // Завершить текущий условный оператор
        ...
        break;

        // и т. д. для любых других расширяемых примитивных команд, поддерживаемых
        // движком TeX

        }

    }else // Нерасширяемый примитив: это макрос
        {
             macrocall()
        }
        //... больше кода удалено
    }
```

### Любовь TeX к глобальным переменным

Возможно, отражая свой возраст и эпоху, в которую он был разработан, исходный код TeX широко использует так называемые [глобальные переменные](https://en.wikipedia.org/wiki/Global_variable)— на самом деле их сотни. По самой своей природе глобальные переменные могут быть изменены/модифицированы из любого места в исходном коде TeX, который для TeX Кнута представляет собой единый монолитный файл, содержащий более 25 000 строк кода и сотни функций. Понять, как работает TeX, не всегда простая задача...

Чтобы обработать `\expandafter`, TeX читает токены из своего текущего ввода, используя функцию под названием `gettoken()` чья задача — создать токен и установить значение нескольких ключевых глобальных переменных, используемых во всем исходном коде TeX. Две такие переменные, обновляемые действием `gettoken()`, используются в реализации `\expandafter`:

* `curtok`: (текущий токен) целочисленное значение только что прочитанного токена;
* `curcmd`: (текущий код команды) код команды, представленной токеном (или символом) `curtok`.

При обработке `\expandafter`$$\mathrm{T\_1T\_2}$$ TeX читает токен $$\mathrm{T\_1}$$ и временно сохраняет его значение (целое число) в локальной переменной под названием `t`. Затем TeX читает $$\mathrm{T\_2}$$ и проверяет, представляет ли этот токен расширяемую команду — проверяя, больше ли код ее команды (`curcmd`) 100. Если да, TeX нужно расширить команду, представленную $$\mathrm{T\_2}$$ и делает еще один вызов функции `expand()`: это пример *рекурсии* потому что `expand()` функция вызывает саму себя. Понимание рекурсивной природы расширения, особенно при использовании `\expandafter`, может помочь понять, как несколько последовательных `\expandafter` команд — то есть, `\expandafter\expandafter\expandafter...` достигают своего результата.

Если токен $$\mathrm{T\_2}$$ расширяем, происходит расширение, и когда рекурсивный вызов `expand()` возвращается, код внутри реализации `\expandafter` повторно вставляет токен $$\mathrm{T\_1}$$ обратно во входные данные. Глобальная переменная `curtok` переприсваивается значению сохраненного токена — хранящемуся в локальной переменной `t`, которое является значением токена $$\mathrm{T\_1}$$— и выполняется вызов функции `backinput().`

#### Функция backinput()

Как следует из названия, эта функция помещает токен «обратно во входные данные». Для этого TeX использует текущее значение глобальной переменной `curtok` чтобы создать список токенов, содержащий один токен (чье целочисленное значение задается `curtok`). TeX также настраивает обработку ввода так, чтобы этот список из одного токена в нужный момент был перечитан TeX как часть последующей обработки ввода. Обратите внимание, что токен $$\mathrm{T\_1}$$ вставляется обратно *после завершения расширения*, что гарантирует, что TeX прочитает этот повторно вставленный токен *до того, как* когда он читает токены, возникающие при расширении $$\mathrm{T\_2}$$.

### Обработка макросов: функция macrocall()

Как уже обсуждалось ранее, все макросы вместе с некоторыми примитивными командами являются расширяемыми, и вся обработка расширения проходит через `expand()` функцию. Однако, `expand()` аккуратно использует `curcmd` значение (текущей команды), чтобы различать расширяемые примитивы и макросы, поскольку процесс расширения макросов обрабатывается специальной функцией под названием `macrocall()`. Макросам нужен специализированный процесс расширения, потому что аргументы макроса и токены-разделители должны сканироваться очень особым и строгим образом; следовательно, этот процесс передается функции, предназначенной для этого: `macrocall()`.

#### Расширение макроса и выполнение макроса

Макрос *расширение* не тот же процесс, что и макрос *выполнение*: расширение макроса — это предварительный этап перед выполнением, который TeX выполняет, чтобы подготовить макрос *к выполнению*. «Выполнение» макроса происходит, когда TeX активно читает и обрабатывает токены, содержащиеся в определении этого макроса (тексте замены) и его аргументах (параметрах).

#### Расширение макроса

Чтобы расширить макрос, TeX сначала проверяет, принимает ли макрос аргументы; если да, `macrocall()` очень тщательно просматривает ввод в поисках токенов, которым суждено стать аргументами макроса. Этот процесс включает проверку ввода пользователя на наличие любых токенов-разделителей, используемых в исходном определении макроса — шаблон токенов, используемый в вызове макроса, должен точно соответствовать шаблону токенов, содержащемуся в сохраненном определении. Однако токены, используемые как разделители, просто отбрасываются TeX: по сути, это лишь форма «пунктуации», которую TeX использует для определения фактических токенов, которым суждено стать аргументами макроса — то есть токенов, которые пользователь намерен обработать с помощью макроса. Для получения дополнительной информации о токенах-разделителях см. [Как на самом деле работают макросы TeX](/latex/ru/drugie-temy/22-how-tex-macros-actually-work-part-4.md).

Для каждого параметра (`#1, #2...#9`) присутствующего в исходном определении макроса, TeX просматривает фактический вызов макроса, чтобы определить, какие токены, предоставленные пользователем, предназначены для каждого параметра (то есть образуют аргументы макроса). Этот процесс создает один или несколько мини-списков токенов: по одному для каждого аргумента макроса.

После того как любые аргументы макроса были обнаружены и их списки токенов подготовлены, TeX извлекает определение макроса (текст замены), хранящееся в его памяти, и организует обработку ввода таким образом, что всякий раз, когда TeX готов прочитать/обработать больше токенов, он будет читать их из текста замены макроса, тем самым выполняя макрос. В соответствующий момент, во время выполнения макроса, списки токенов, представляющие аргументы макроса, будут подставлены в нужное место внутри текста замены макроса.

И снова, расширение команды макроса означает *удаление* этой команды макроса (токена) из ввода и *замену* ее списком токенов, хранящимся как текст замены макроса.

Для подробного рассмотрения обработки макросов в TeX см. серию статей из шести частей [Как на самом деле работают макросы TeX?](/latex/ru/drugie-temy/01-a-six-part-series-how-do-tex-macros-actually-work.md)

[Часть 1](/latex/ru/podrobnye-stati/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md) [Часть 2](/latex/ru/podrobnye-stati/22-how-does-expandafter-work-the-meaning-of-expansion.md) [Часть 3](/latex/ru/podrobnye-stati/21-how-does-expandafter-work-tex-uses-temporary-token-lists.md) [Часть 4](/latex/ru/podrobnye-stati/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md) [Часть 5](/latex/ru/podrobnye-stati/17-how-does-expandafter-work-a-detailed-macro-case-study.md) [Часть 6](/latex/ru/podrobnye-stati/18-how-does-expandafter-work-a-detailed-study-of-consecutive-expandafter-commands.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/ru/podrobnye-stati/20-how-does-expandafter-work-from-basic-principles-to-exploring-tex-s-source-code.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
