4

In the MWE

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand \DefGrRules { m } { \inft_def_gr_rules:n { #1 } }

\NewDocumentCommand \GrammarShowRules { } { \inft_grammar_show_rules: }

\seq_new:N \l__inft_gr_rules_seq

\cs_new:Nn \inft_def_gr_rules:n
{
  \seq_set_from_clist:Nn \l__inft_gr_rules_seq { #1 }   
}

\cs_new:Nn \inft_grammar_show_rules:
{
  \seq_set_map:NNn \l_tmpa_seq \l__inft_gr_rules_seq
  {
    \seq_set_split:Nnn \l_tmpb_seq {->} { ##1 }
    \seq_show:N \l_tmpb_seq
    \seq_count:N \l_tmpb_seq
    { \seq_item:Nn \l_tmpb_seq { 1 } }
    & \to
    { \seq_item:Nn \l_tmpb_seq { 2 } }
  }
  \seq_use:Nn \l_tmpa_seq { \\ }
}

\ExplSyntaxOff

\begin{document}

\DefGrRules{S -> X | , X -> aXYZ | aYZ, ZY -> YZ, aY -> ab, bY -> bb, bZ -> bc, cZ -> cc}

\begin{align*}
\GrammarShowRules
\end{align*}

\end{document}  

\l_tmpb_seq seems to have two items as confirmed by \seq_show:N \l_tmpb_seq. However, \seq_count:N \l_tmpb_seq returns 0, and the commands for accessing the items expand to nothing. What is the reason for this?

My intention is to replace -> by \to, furthermore | by \mathrel{} \middle| \mathrel{} and to process all the other parts by a further command that is omitted in the MWE, since not even the splitting works as desired.

  • 1
    The third argument to \seq_set_map:NNn is subject to full expansion, so it cannot contain directly assignments. – egreg Nov 23 '17 at 22:24
  • @egreg O.k., my approach is obviously wrong and needs to be replaced. However, why does \seq_show:N display a sequence with two items if the assignment is not supposed to work? – Matthias Nov 23 '17 at 22:31
  • I guess it's just a coincidence. – egreg Nov 23 '17 at 22:34
3

The third argument to \seq_set_map:NNn is subject to full expansion. You can use an expandable method for splitting the argument at ->:

\documentclass{article}

\usepackage{lmodern}
\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand \DefGrRules { m } { \inft_def_gr_rules:n { #1 } }

\NewDocumentCommand \GrammarShowRules { } { \inft_grammar_show_rules: }

\seq_new:N \l__inft_gr_rules_seq

\cs_new_protected:Nn \inft_def_gr_rules:n
 {
  \seq_set_from_clist:Nn \l__inft_gr_rules_seq { #1 }   
 }

\cs_new:Nn \inft_grammar_show_rules:
 {
  \seq_set_map:NNn \l_tmpa_seq \l__inft_gr_rules_seq
   {
    \__inft_gr_split:w ##1 \q_stop
   }
  \seq_use:Nn \l_tmpa_seq { \\ }
 }
\cs_new:Npn \__inft_gr_split:w #1 -> #2 \q_stop
 {
  \exp_not:n { #1 & \to #2 }
 }

\ExplSyntaxOff

\begin{document}

\DefGrRules{
  S -> X |,
  X -> aXYZ | aYZ,
  ZY -> YZ,
  aY -> ab,
  bY -> bb,
  bZ -> bc,
  cZ -> cc
}

\begin{align*}
\GrammarShowRules
\end{align*}

\end{document}  

enter image description here

  • The double backslash needs to be removed from \__inft_gr_split:w since it is already part of \seq_use:Nn. – Matthias Nov 23 '17 at 22:42
  • @Matthias Yes, you're right – egreg Nov 23 '17 at 22:49
3

Just for the sake of variety, here's a way to achieve your typesetting objective via a LuaLaTeX-based approach. The preamble below sets up two LaTeX macros, \DefGrRules and \GrammarShowRules, which act as wrappers for two corresponding Lua functions, called DefGrRules and GrammarShowRules. The former function employs Lua's powerful string.gsub function to do most of the work.

enter image description here

\documentclass{article}
\usepackage{amsmath} % for 'align*' env.

%% Lua-side code
\usepackage{luacode}
\begin{luacode}
Rule = ""  -- initialize string variable    
function DefGrRules ( s )
    s = s:gsub ( "->" , "&\\to" )
    s = s:gsub ( "|"  , "\\mathrel{}\\vert\\mathrel{}" )
    s = s:gsub ( ","  , "\\\\"  )
    Rule = s -- store result in string variable "Rule"
end    
function GrammarShowRules ()
    tex.sprint ( "\\begin{align*}" .. Rule .. "\\end{align*}" )
end   
\end{luacode}

%% TeX-side code    
\newcommand\DefGrRules[1]{\directlua{DefGrRules(\luastringN{#1})}}
\newcommand\GrammarShowRules{\directlua{GrammarShowRules()}}

\begin{document}   
\DefGrRules{S -> X | , X -> aXYZ | aYZ, ZY -> YZ, aY -> ab, bY -> bb, bZ -> bc, cZ -> cc}    
\GrammarShowRules  
\end{document} 
  • 1
    This is a very nice alternative. – Matthias Nov 23 '17 at 23:29

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.