![Можно ли выполнить команду, сохраненную в виде текста в переменной?](https://rvso.com/image/286957/%D0%9C%D0%BE%D0%B6%D0%BD%D0%BE%20%D0%BB%D0%B8%20%D0%B2%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D1%8C%20%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%83%2C%20%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%BD%D1%83%D1%8E%20%D0%B2%20%D0%B2%D0%B8%D0%B4%D0%B5%20%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%B0%20%D0%B2%20%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%BE%D0%B9%3F.png)
У меня есть несколько сложных выражений с кучей вложенных команд, с которыми трудно работать. Чтобы решить эту проблему, я написал парсер с использованием pgfparser, который создает выражения для меня. Затем я могу скопировать вывод обратно в LaTeX, и он выведет то, что мне нужно.
Мне было интересно, можно ли это автоматизировать. Я могу сохранить текст (последовательность команд) в переменной, но тогда я не могу найти способ запустить команды в переменной
Сам парсер не представляет особого интереса, но, по сути, это упрощенная версия того, что у меня есть:
\documentclass{standalone}
\usepackage[T1]{fontenc}
\usepackage{pgf}
\usepgfmodule{parser}
\pgfparserdef{mweparser}{initial}{\meaning [}{\textbackslash overline\{}
\pgfparserdef{mweparser}{initial}{\meaning ]}{\}}
\pgfparserdef{mweparser}{initial}{\meaning A}{A}
\pgfparserdef{mweparser}{initial}{subscript character _}{\_\{\pgfparserswitch{subscript}}
\pgfparserdef{mweparser}{subscript}{\meaning +}{\textbackslash hat\{\pgfparserswitch{edgename}}
\pgfparserdef{mweparser}{subscript}{\meaning -}{\textbackslash check\{\pgfparserswitch{edgename}}
\pgfparserdef{mweparser}{edgename}{\meaning a}{a\}\pgfparserswitch{subscript}}
\pgfparserdef{mweparser}{edgename}{\meaning b}{b\}\pgfparserswitch{subscript}}
\pgfparserdef{mweparser}{subscript}{subscript character _}{\}\pgfparserswitch{initial}}
\pgfparserdef{mweparser}{all}{the character ;}{\pgfparserswitch{final}}
\begin{document}
\pgfparserparse{mweparser}[A_+a-b-a_[A_+a+b-a_]];%
\end{document}
Это выведет:
\overline{A_{\hat{a}\check{b}\check{a}}\overline{A_{\hat{a}\hat{b}\check{a}}}}
Что я и хотел бы запустить (в математическом режиме). Я могу сохранить этот текст в переменной, но не вижу, как его запустить.
Я новичок в этом деле, поэтому прошу прощения, если я сделал что-то не так.
решение1
Я не совсем понимаю, как работает парсер PGF, но в результате вашего кода вы получаете строку, которая не является тем, что вам нужно: \textbackslash
это не обратная косая черта, а команда на ее печать.
Вот реализация с помощью l3regex
, анализатора регулярных выражений LaTeX3; желаемый результат был добавлен для проверки того, что делают макросы.
\documentclass[border=3,varwidth]{standalone}
\usepackage[T1]{fontenc}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\term}{m}
{
\dquick_term:n { #1 }
}
\tl_new:N \l__dquick_input_tl
\cs_new_protected:Npn \dquick_term:n #1
{
\tl_set:Nn \l__dquick_input_tl { #1 }
%% subscripts (works so long you don't have nested subscripts)
\regex_replace_all:nnN { \_(.*?)\_ } { \cD\_\cB\{\1\cE\} } \l__dquick_input_tl
%% [ becomes \overline\bgroup (nesting is allowed)
\regex_replace_all:nnN { \[ } { \c{overline}\c{bgroup} } \l__dquick_input_tl
%% ] becomes \egroup
\regex_replace_all:nnN { \] } { \c{egroup} } \l__dquick_input_tl
%% +<char> becomes \hat{<char>}
\regex_replace_all:nnN { \+(.) } { \c{hat}\cB\{\1\cE\} } \l__dquick_input_tl
%% -<char> becomes \check{<char>}
\regex_replace_all:nnN { \-(.) } { \c{check}\cB\{\1\cE\} } \l__dquick_input_tl
$\tl_use:N \l__dquick_input_tl$
}
\ExplSyntaxOff
\begin{document}
\term{[G_+a-b-c_[H_+a+a-c_]]}
$\overline{G_{\hat{a}\check{b}\check{c}}\overline{H_{\hat{a}\hat{a}\check{c}}}}$
\end{document}
Немного другая версия, которая позволяет указывать символы-разделители (они должны быть разными) для вложенных макросов, здесь показана с \overline
.
\documentclass[border=3,varwidth]{standalone}
\usepackage[T1]{fontenc}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\term}{m}
{
\dquick_term:n { #1 }
}
\tl_new:N \l__dquick_input_tl
\cs_new_protected:Npn \dquick_term:n #1
{
\tl_set:Nn \l__dquick_input_tl { #1 }
%% subscripts (works so long you don't have nested subscripts)
\regex_replace_all:nnN { \_(.*?)\_ } { \cD\_\cB\{\1\cE\} } \l__dquick_input_tl
%% brackets can be nested, this requires a slower routine
\dquick_replace_nested:nnn { \[ } { \] } { overline }
%% +<char> becomes \hat{<char>}
\regex_replace_all:nnN { \+(.) } { \c{hat}\cB\{\1\cE\} } \l__dquick_input_tl
%% -<char> becomes \check{<char>}
\regex_replace_all:nnN { \-(.) } { \c{check}\cB\{\1\cE\} } \l__dquick_input_tl
\tl_use:N \l__dquick_input_tl
}
\cs_new_protected:Npn \dquick_replace_nested:nnn #1 #2 #3
{% #1 is the left delimiter
% #2 is the right delimiter
% #3 is the macro name for replacement
\regex_match:nVT { #1 ( [^#1#2]*? ) #2 } \l__dquick_input_tl
{
\regex_replace_all:nnN { #1 ( [^#1#2]*? ) #2 } { \c{#3}\cB\{\1\cE\} } \l__dquick_input_tl
\dquick_replace_nested:nnn { #1 } { #2 } { #3 }
}
}
\cs_generate_variant:Nn \regex_match:nnT { nV }
\ExplSyntaxOff
\begin{document}
$\term{[G_+a-b-c_[H_+a+a-c_]]}$
$\overline{G_{\hat{a}\check{b}\check{c}}\overline{H_{\hat{a}\hat{a}\check{c}}}}$
\end{document}