7

Here's a example with the "! Improper alphabetic constant" error:

%% this is ok  
\newcount\mychar
\mychar=\number`a\relax
\showthe a       % shows You can't use `the letter a' after \the
\showthe\mychar  % shows 97

%% this is not ok
\let\Char=a     
\showthe\Char    % shows You can't use `the letter a' after \the
\mychar=\number`\Char\relax  % here error comes
\showthe\mychar

Setting the counter should expand till non-expandable token (in this case it's \relax). Question: why is \Char not expanded?

7

\Char is not expanded because it is not an expandable token. Unlike \def\Char{a} which expands to a \let defines a token that essentially is a and like a it does not expand.

The only way to get hold of this in classic TeX is to take \meaning\Char which will be

the letter a

split that up on spaces, and if the first two words are the letter take the letter which will be a and then use the `a syntax as you used.

Look at the source of the bm package which does a lot of this:-)


Working example (plain TeX)

\newcount\mychar

\def\zz#1{%
% catcode 11 (letter)
\ifcat a#1%
\expandafter\zza\meaning#1 \relax
\else
%other cases here
-1
\fi}

\def\zza#1 #2 #3 #4\relax{`#3 }

\let\Char=a     



\mychar=\zz{a}
\immediate\write20{a=\the\mychar}

\mychar=\zz{\Char}
\immediate\write20{\Char=\the\mychar}




\bye

which produces a log

a=97
\Char =97

showing the macro accepts explicit or implicit character tokens.

| improve this answer | |
  • I knew how to do it with meaning, just wanted to find a simpler solution :) Thanks I accept the answer. – Linuxss Dec 4 '13 at 12:17
2

Here's an implementation with l3regex; the number is stored in \l_linuxss_code_int for later usage.

One can extend the testing by acting on the search regular expression; this one catches the letter or the character.

\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\getlettercode}{m}
 {
  \linuxss_getlettercode:N #1
  \int_to_arabic:n { \l_linuxss_code_int } % just for testing
 }

\int_new:N \l_linuxss_code_int
\tl_new:N \l_linuxss_meaning_tl
\regex_const:Nn \c_linuxss_search_regex { \A the \s (letter|character) \s }

\cs_new_protected:Npn \linuxss_getlettercode:N #1
 {
  \tl_set:Nx \l_linuxss_meaning_tl { \token_to_meaning:N #1 }
  \regex_match:NVTF \c_linuxss_search_regex \l_linuxss_meaning_tl
   {
    \regex_replace_once:NnN \c_linuxss_search_regex { } \l_linuxss_meaning_tl
    \int_set:Nx \l_linuxss_code_int { ` \l_linuxss_meaning_tl }
   }
   {
    \int_set:Nn \l_linuxss_code_int { -1 }
   }
 }
\cs_generate_variant:Nn \regex_match:NnTF { NV }
\cs_generate_variant:Nn \int_set:Nn { Nx }
\ExplSyntaxOff

\begin{document}

\let\Chara=a
$\getlettercode{\Chara}=\number`a$

\let\Charz=z
$\getlettercode{\Charz}=\number`z$

\let\Charpipe=|
$\getlettercode{\Charpipe}=\number`|$

$\getlettercode{\let}=-1$

\end{document}

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.