%%
%% This is file `simplebnf.sty'.
%%
%% ---------------------------------------------------------------------------
%% The simplebnf package --- A simple package to format Backus-Naur form
%% Maintained by Jay Lee
%% E-mail: jaeho.lee@snu.ac.kr
%% Released under the MIT License.
%% ---------------------------------------------------------------------------
%%
\RequirePackage{expl3,xparse}
% mathtools is needed for the \Coloneqq simbol
\RequirePackage{mathtools}
\ProvidesExplPackage
  {simplebnf}
  {2020/09/01}
  {0.2.0}
  {A simple package to format Backus–Naur form}

\cs_generate_variant:Nn \seq_set_split:Nnn {NVn}
\tl_new:N \g__simplebnf_defeq_tl
\tl_gset:Nn \g__simplebnf_defeq_tl { \ensuremath{\Coloneqq} }

\tl_new:N \g__simplebnf_defor_tl
\tl_gset:Nn \g__simplebnf_defor_tl { \ensuremath{|} }

\seq_new:N \l__input_seq
\seq_new:N \l__term_seq
\tl_new:N \l__term_tl
\tl_new:N \l__keypairs_tl
\tl_new:N \l__table_tl
\seq_new:N \l__keypairs_seq
\bool_new:N \l__first_rhs

%% Typeset a single rhs of a production.
%% \l__first_rhs = true  => `::=' already typeset
%% \l__first_rhs = false => move to a newline and typeset `|'
%% #1 - rhs : annot or rhs
\cs_new:Nn \simplebnf_typeset_rhs:n
{
  \bool_if:NTF \l__first_rhs
    {
      \bool_set_false:N \l__first_rhs
    }
    {
      \tl_put_right:Nn \l__table_tl { \\ & \g__simplebnf_defor_tl & }
    }

  \regex_split:nnNTF { : } { #1 } \l_tmpa_seq
    {
      \seq_pop_left:NNT \l_tmpa_seq \l_tmpa_tl
        {
          \tl_set:Nx \l_tmpa_tl { \bnfexpr { \l_tmpa_tl } }
          \tl_put_right:NV \l__table_tl \l_tmpa_tl
        }

      \tl_put_right:Nn \l__table_tl { & }

      \seq_pop_left:NNT \l_tmpa_seq \l_tmpb_tl
        {
          \tl_set:Nx \l_tmpb_tl { \bnfannot { \l_tmpb_tl } }
          \tl_put_right:NV \l__table_tl \l_tmpb_tl
        }
    }
    {
      \tl_put_right:Nn \l__table_tl { \bnfexpr { #1 } &}
    }
}

\NewDocumentCommand \bnfexpr { m } { \texttt { #1 } }
\NewDocumentCommand \bnfannot { m } { \textit{ #1 } }

\NewDocumentEnvironment { bnfgrammar } { +b }
  {
    %% \l__input_seq is a list of term definitions.
    \regex_split:nnN { ;; } { #1 } \l__input_seq
    \begin{center}
      \tl_set:Nn \l__table_tl
        {
          \begin{tabular}{lcll}
        }
    \bool_set_true:N \l_tmp_first_term % Is this the first term in this grammar?
    \seq_map_inline:Nn \l__input_seq
      {
        %% \l__term_seq    - (term, rhses)...
        %% \l__term_tl     - term
        %% \l__keypairs_tl - rhses
        \regex_split:nnN { ::= } { ##1 } \l__term_seq
        \seq_pop_left:NN \l__term_seq \l__term_tl
        \seq_pop_left:NN \l__term_seq \l__keypairs_tl

        \regex_replace_once:nnN { ^\s+ } {} \l__term_tl

        \bool_if:NTF \l_tmp_first_term
          {
            \bool_set_false:N \l_tmp_first_term
          }
          {
            \tl_put_right:Nn \l__table_tl { \\ }
          }
        \tl_put_right:Nx \l__table_tl
          {
            \bnfexpr { \l__term_tl } & \g__simplebnf_defeq_tl &
          }
        %% \l__keypairs_seq - (rhs:annot | rhs)...
        \seq_set_split:NnV \l__keypairs_seq { | } \l__keypairs_tl

        \bool_set_true:N \l__first_rhs
        \seq_map_function:NN \l__keypairs_seq \simplebnf_typeset_rhs:n
      }

    \tl_put_right:Nn \l__table_tl { \end{tabular} }
    \tl_use:N \l__table_tl
    \end{center}
  }
  { }

%% The MIT License (MIT)
%%
%% Copyright © 2019-2020 Jay Lee <jaeho.lee@snu.ac.kr>
%%
%% Permission is hereby granted, free of charge, to any person obtaining
%% a copy of this software and associated documentation files (the "Software"),
%% to deal in the Software without restriction, including without limitation
%% the rights to use, copy, modify, merge, publish, distribute, sublicense,
%% and/or sell copies of the Software, and to permit persons to whom the
%% Software is furnished to do so, subject to the following conditions:
%%
%% The above copyright notice and this permission notice shall be included
%% in all copies or substantial portions of the Software.
%%
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
%% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
%% IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
%% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
%% TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
%% OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
%%
%% End of file `simplebnf.sty'.
