5

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.

3
  • 1
    The third argument to \seq_set_map:NNn is subject to full expansion, so it cannot contain directly assignments.
    – egreg
    Commented Nov 23, 2017 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
    Commented Nov 23, 2017 at 22:31
  • I guess it's just a coincidence.
    – egreg
    Commented Nov 23, 2017 at 22:34

2 Answers 2

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

2
  • The double backslash needs to be removed from \__inft_gr_split:w since it is already part of \seq_use:Nn.
    – Matthias
    Commented Nov 23, 2017 at 22:42
  • @Matthias Yes, you're right
    – egreg
    Commented Nov 23, 2017 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
  • 1
    This is a very nice alternative.
    – Matthias
    Commented Nov 23, 2017 at 23:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .