# Constructing a command for Physical Dimension - parsing character by character

I wish to have a dedicated command for printing physical dimension. Something like \phydimen{M2L-3T-1}. This should output the same as $\textrm{M}^2\textrm{L}^{-3}\textrm{T}^{-1}$.

I find that the \ce command of mhchem package is quite suitable. So I hack it to do \newcommand{\phydimen}[1]{\ce{#1}} and then issue a command \phydimen{ML^2T^{-2}} to print the dimension. However I still have to use the pesky ^ and { }. The default \ce behavior is to push the numbers as subscript.

I want \phydimen to automatically detect when a (positive or negative) integer is in the argument and push it to "power". Also \phydimen should be able to accept more characters than M,L,T. Also if lowercase is supplied, it should automatically convert it to uppercase.

How do I parse the arguments character by character and decide whether it is a letter or positive integer or negative integer?

MWE:

\documentclass{article}
\usepackage{mhchem}

\newcommand{\phydimen}[1]{\ce{#1}}
\begin{document}
$\textrm{M}^2\textrm{L}^{-3}\textrm{T}^{-1}$

\phydimen{ML^2T^{-2}} % instead I want \phydimen{ML2T-2}
\end{document}


You can use regular expressions:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\phydimen}{m}
{
\tl_set:Nn \l_tmpa_tl { #1 }
\regex_replace_all:nnN { (\-?\d+) } { \cU\^\cB\{\1\cE\} } \l_tmpa_tl
\ensuremath { \mathrm { \tl_use:N \l_tmpa_tl } }
}

\ExplSyntaxOff

\begin{document}

\phydimen{ML2T-2}

\end{document}


The search expression matches a possibly signed integer, the replacement expression specifies “superscript character, left brace, the match, right brace”.

• Thanks a lot. This is exactly what I wanted. After @mhchem's comment, I was digging regex manipulation of l3regex to figure out. – magguu Feb 16 '18 at 11:58

Here I use listofitems to conduct a 2-tier parsing, looking for digits at the first level and for the negative sign at the second level.

\documentclass{article}
\usepackage{listofitems}
\newcommand\phydimen[1]{%
\setsepchar{0||1||2||3||4||5||6||7||8||9/-}%

I would not recommend using \ce inside your command. It does way more stuff than just changing the font. It would double-parse the input, I think this will not be efficient.
The command you want to create already exists within mhchem for MathJax. Why it does not exist for LaTeX is explained in the question How to use MathJax mhchem \pu{} command in LaTex?, including reasons to use another command instead.