Переход к чему-либо, когда выражение не может быть оценено с помощью fpeval

Переход к чему-либо, когда выражение не может быть оценено с помощью fpeval

Я хотел бы разработать \comparatorрасширяемую команду, которая опирается на fpeval3 ветви:

  • истинная ветвькогда сравнение равно 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), но улавливает основные литеральные синтаксисы.

Связанный контент