
Я хотел бы разработать \comparator
расширяемую команду, которая опирается на fpeval
3 ветви:
- истинная ветвькогда сравнение равно 1
- ложная ветвькогда сравнение равно нулю
- недействительная ветвькогда сравнение не может быть выполнено (вместо возврата ошибки компиляции)
Вот текущий код, который я использую:
\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xfp}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\compare}{r[] m m m m m}{
\compare_evaluation:eeennn{#1}{#2}{#3}{#4}{#5}{#6}
}
\cs_new:Nn \compare_evaluation:nnnnnn{
\compare_result:ennn{\fpeval{#2 #1 #3}}{#4}{#5}{#6}
}
\cs_new:Nn \compare_result:nnnn{
\str_case:nnTF{#1}{
{0}{#3}
{1}{#2}
}{}{#4}
}
\cs_generate_variant:Nn \compare_evaluation:nnnnnn{eeennn}
\cs_generate_variant:Nn \compare_result:nnnn{ennn}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{c}
\compare[<]{1.5}{2.5}{true}{false}{invalid} \\
\compare[<]{2.5}{1.5}{true}{false}{invalid} \\
\compare[<]{xx}{xx}{true}{false}{invalid} \\ % CRASHES
\end{tabular}
\end{document}
который, конечно же, дает сбой на последней строке теста.
ВОПРОС:Как сделать так, чтобы он компилировался и правильно ветвлялся (здесь для печати invalid
)?
решение1
Если расширяемость не является обязательным требованием, вы можете проверить синтаксис с помощью регулярного выражения.
\documentclass[preview = true, varwidth = true]{standalone}
% These only needed in old latex releases
% \usepackage{xparse}
% \usepackage{xfp}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\compare}{r[] m m m m m}{
\compare_evaluation:eeennn{#1}{#2}{#3}{#4}{#5}{#6}
}
\cs_new:Nn \compare_evaluation:nnnnnn{
\regex_match:nnTF
{^[0-9]*(\.[0-9]*)?([eE][0-9]+)?@@@[0-9]*(\.[0-9]*)?([eE][0-9]+)?$}
{#2@@@#3}
{
\compare_result:ennn{\fpeval{#2 #1 #3}}{#4}{#5}{#6}
}
{#6}
}
\cs_new:Nn \compare_result:nnnn{
\str_case:nnTF{#1}{
{0}{#3}
{1}{#2}
}{}{#4}
}
\cs_generate_variant:Nn \compare_evaluation:nnnnnn{eeennn}
\cs_generate_variant:Nn \compare_result:nnnn{ennn}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{c}
\compare[<]{1.5}{2.5}{true}{false}{invalid} \\
\compare[<]{2.5}{1.5}{true}{false}{invalid} \\
\compare[<]{2.5e2}{15e3}{true}{false}{invalid} \\
\compare[<]{xx}{xx}{true}{false}{invalid} \\ % CRASHES
\end{tabular}
\end{document}
здесь я предположил, @@@
что безопасно использовать в качестве разделителя, вы можете использовать regex для двух аргументов по отдельности или использовать пользовательскую команду tken, но это показывает основную идею. Также regex может не иметь точно такой же синтаксис, как l3fp в крайних случаях (и не охватывает выражения fp), но улавливает основные литеральные синтаксисы.