summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/simplebnf/simplebnf.sty
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/simplebnf/simplebnf.sty')
-rw-r--r--macros/latex/contrib/simplebnf/simplebnf.sty126
1 files changed, 100 insertions, 26 deletions
diff --git a/macros/latex/contrib/simplebnf/simplebnf.sty b/macros/latex/contrib/simplebnf/simplebnf.sty
index a8ae523036..fd7b707ff7 100644
--- a/macros/latex/contrib/simplebnf/simplebnf.sty
+++ b/macros/latex/contrib/simplebnf/simplebnf.sty
@@ -13,11 +13,13 @@
\RequirePackage{mathtools}
\ProvidesExplPackage
{simplebnf}
- {2020/09/01}
- {0.2.0}
+ {2022/05/07}
+ {0.3.0}
{A simple package to format Backus–Naur form}
-\cs_generate_variant:Nn \seq_set_split:Nnn {NVn}
+\cs_generate_variant:Nn \regex_split:nnNTF {nVNTF}
+\cs_generate_variant:Nn \regex_split:NnN {NVN}
+
\tl_new:N \g__simplebnf_defeq_tl
\tl_gset:Nn \g__simplebnf_defeq_tl { \ensuremath{\Coloneqq} }
@@ -32,6 +34,9 @@
\seq_new:N \l__keypairs_seq
\bool_new:N \l__first_rhs
+\regex_new:N \g_simplebnf_rhs_newline_r
+\regex_new:N \g_simplebnf_rhs_nb_r
+
%% Typeset a single rhs of a production.
%% \l__first_rhs = true => `::=' already typeset
%% \l__first_rhs = false => move to a newline and typeset `|'
@@ -43,15 +48,18 @@
\bool_set_false:N \l__first_rhs
}
{
- \tl_put_right:Nn \l__table_tl { \\ & \g__simplebnf_defor_tl & }
+ \tl_put_right:Nn \l__table_tl { \\ && \g__simplebnf_defor_tl & }
}
- \regex_split:nnNTF { : } { #1 } \l_tmpa_seq
+ \tl_set:Nn \l_tmpa_tl { #1 }
+ \regex_replace_once:nnN { ^\s+ } {} \l_tmpa_tl
+ \regex_replace_once:nnN { \s+$ } {} \l_tmpa_tl
+ \regex_split:nVNTF { : } \l_tmpa_tl \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
+ \regex_replace_all:NnN \g_simplebnf_rhs_nb_r { \c{g__simplebnf_defor_tl} } \l_tmpa_tl
+ \tl_put_right:Nx \l__table_tl { \bnfexpr { \l_tmpa_tl } }
}
\tl_put_right:Nn \l__table_tl { & }
@@ -63,34 +71,67 @@
}
}
{
- \tl_put_right:Nn \l__table_tl { \bnfexpr { #1 } &}
+ \regex_replace_all:NnN \g_simplebnf_rhs_nb_r { \c{g__simplebnf_defor_tl} } \l_tmpa_tl
+
+ \tl_put_right:Nx \l__table_tl { \bnfexpr { \l_tmpa_tl } }
+ \tl_put_right:Nn \l__table_tl { & }
+ }
+}
+
+%% Typeset a single lhs of a production.
+%% #1 - lhs : either term or (term : annotation)
+\cs_new:Nn \simplebnf_typeset_lhs:n
+{
+ \tl_set:Nx \l_tmpa_tl { #1 }
+ \regex_replace_once:nnN { ^\s+ } {} \l_tmpa_tl
+ \regex_replace_once:nnN { \s+$ } {} \l_tmpa_tl
+
+ \regex_split:nVNTF { : } \l_tmpa_tl \l_tmpa_seq
+ {
+ \seq_pop_right:NN \l_tmpa_seq \l_tmpa_tl
+ \tl_put_right:Nx \l__table_tl
+ {
+ \bnfannot{\l_tmpa_tl}
+ }
+ \seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
+ \tl_put_right:Nx \l__table_tl
+ {
+ & \bnfexpr { \l_tmpa_tl }
+ }
+ }
+ {
+ \tl_put_right:Nx \l__table_tl
+ {
+ & \bnfexpr { \l_tmpa_tl }
+ }
}
}
\NewDocumentCommand \bnfexpr { m } { \texttt { #1 } }
\NewDocumentCommand \bnfannot { m } { \textit{ #1 } }
-\NewDocumentEnvironment { bnfgrammar } { +b }
+%% Typeset a BNF grammar.
+%% #1 - tabular specification (llcll)
+%% #2 - regexp for newline separator for rhses
+%% #2 - regexp for non-breaking separator for rhses
+%% #3 - grammar
+\NewDocumentEnvironment { bnfgrammar } { O{llcll} O{[^\|]\|[^\|]} O{\|\|} +b }
{
+ \regex_gset:Nn \g_simplebnf_rhs_newline_r { #2 }
+ \regex_gset:Nn \g_simplebnf_rhs_nb_r { #3 }
+
%% \l__input_seq is a list of term definitions.
- \regex_split:nnN { ;; } { #1 } \l__input_seq
+ \regex_split:nnN { ;; } { #4 } \l__input_seq
\begin{center}
\tl_set:Nn \l__table_tl
{
- \begin{tabular}{lcll}
+ \begin{tabular}{#1}
}
+
\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
-
+ %% If not-first, add newline
\bool_if:NTF \l_tmp_first_term
{
\bool_set_false:N \l_tmp_first_term
@@ -98,15 +139,48 @@
{
\tl_put_right:Nn \l__table_tl { \\ }
}
- \tl_put_right:Nx \l__table_tl
+
+ \regex_split:nnNTF { ::= } { ##1 } \l__term_seq
+ % Parse a ::= definition
{
- \bnfexpr { \l__term_tl } & \g__simplebnf_defeq_tl &
+ %% \l__term_seq - (lhs, rhses)...
+ %% \l__term_tl - lhs
+ %% \l__keypairs_tl - rhses
+ \seq_pop_left:NN \l__term_seq \l__term_tl
+ \seq_pop_left:NN \l__term_seq \l__keypairs_tl
+
+ \simplebnf_typeset_lhs:n{\l__term_tl}
+ \tl_put_right:Nx \l__table_tl
+ {
+ & \g__simplebnf_defeq_tl &
+ }
+ %% \l__keypairs_seq - (rhs:annot | rhs)...
+ \regex_split:NVN \g_simplebnf_rhs_newline_r \l__keypairs_tl \l__keypairs_seq
+
+ \bool_set_true:N \l__first_rhs
+ \seq_map_function:NN \l__keypairs_seq \simplebnf_typeset_rhs:n
}
- %% \l__keypairs_seq - (rhs:annot | rhs)...
- \seq_set_split:NnV \l__keypairs_seq { | } \l__keypairs_tl
+ {
+ % Else, parse a \in declaration
+ \regex_split:nnNTF { \c{in} } { ##1 } \l__term_seq
+ {
+ %% \l__term_seq - (lhs, rhs)
+ \seq_pop_left:NN \l__term_seq \l_tmpa_tl
- \bool_set_true:N \l__first_rhs
- \seq_map_function:NN \l__keypairs_seq \simplebnf_typeset_rhs:n
+ \simplebnf_typeset_lhs:n{\l_tmpa_tl}
+ \tl_put_right:Nn \l__table_tl
+ {
+ & $\in$ & $
+ }
+ \seq_pop_left:NN \l__term_seq \l_tmpa_tl
+ \tl_put_right:NV \l__table_tl \l_tmpa_tl
+ \tl_put_right:Nn \l__table_tl
+ {
+ $ &
+ }
+ }
+ { \msg_error:nn {simplebnf} { Could not parser ##1 } }
+ }
}
\tl_put_right:Nn \l__table_tl { \end{tabular} }