我想用 ConTeXt 编写 BNF 规则。我发现这个 BNF 模块并尝试加载它:
\usemodule[bnf]
然而,在加载时,ConTeXt 出现以下错误:
tex error > tex error on line 157 in file /usr/local/texlive/2016/texmf-dist/tex/context/third/bnf/t-bnf.tex: ! Undefined control sequence
<argument> \c!terminalstart
=\tttf
\syst_helpers_process_comma_item #1,#2->\if ,#1
,\expandafter \syst_helpers_p...
<argument> \c!terminalstart =\tttf , \c!terminalstop
=, \c!nonterminalstart =\mathematics
\syst_helpers_get_parameters ...cess_comma_item #1
,],\_e_o_p_
l.157 \c!indentnext=\v!no]
147 \def\setupbnfgrammar%
148 {\dosingleargument\dosetupbnfgrammar}
149
150 \setupbnfgrammar
151 [\c!terminalstart=\tttf,
152 \c!terminalstop=,
153 \c!nonterminalstart=\mathematics{\langle},
154 \c!nonterminalstop=\mathematics{\rangle},
155 \c!is={ \mathematics{\longrightarrow}},
156 \c!option=\mathematics{\vert},
157 >> \c!indentnext=\v!no]
158
159 %D \macros
160 %D {BNF}
161 %D
162 %D We also define a useful abbreviation to be used for header texts and labels.
163
164 \logo[BNF]{bnf}
165
166 %D And we use it here:
167
我认为发生这种情况是因为 BNF 模块是为旧版本的 ConTeXt 编写的。有办法解决这个问题吗?
答案1
看起来这个模块是为 MKII 制作的。您可以通过重写几个宏来使其与 MKIV 配合使用。该模块完全损坏,因为它甚至不能与 MKII 配合使用。
% Missing constants
\setinterfaceconstant{terminalstart}{terminalstart}
\setinterfaceconstant{terminalstop}{terminalstop}
\setinterfaceconstant{nonterminalstart}{nonterminalstart}
\setinterfaceconstant{nonterminalstop}{nonterminalstop}
\setinterfaceconstant{is}{is}
% Missing variables
\setinterfacevariable{bnfgrammar}{bnfgrammar}
\setinterfacevariable{bnfgrammars}{bnfgrammars}
\usemodule[bnf]
\unprotect
\bgroup
\catcode`:\activecatcode
\catcode`|\activecatcode
\catcode`"\activecatcode
\catcode`'\activecatcode
\gdef:{\@@bnfis}
\gdef|{\@@bnfoption}
\gdef"{\thinspace\bgroup\@@bnfterminalstart\tt%
\def"{\@@bnfterminalstop\egroup\thinspace}}
\gdef'{\thinspace\bgroup\@@bnfterminalstart\tt%
\def'{\@@bnfterminalstop\egroup\thinspace}}
\egroup
\def\complexstartbnfgrammar[#1]%
{\endgraf\nobreak\medskip
\begingroup
\setupbnfgrammar[#1]%
\chardef\bnfsinglequote=`'
\catcode`:\activecatcode
\catcode`|\activecatcode
\catcode`"\activecatcode
\catcode`'\activecatcode
\catcode`<=13
\let\par=\bnfgrammarline
\obeylines}
\protect
\starttext
\startplacebnfgrammar[title={An example of a placed grammar.}]
\startbnfgrammar
<exp>: <num> | <num> "+" <num>
<num>: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
\stopbnfgrammar
\stopplacebnfgrammar
\stoptext
这是我将模块移植到 MKIV 的卑微尝试。
\startmodule [bnf-mkiv]
\unprotect
\startinterface all
\setinterfaceconstant {terminalstart} {terminalstart}
\setinterfaceconstant {terminalstop} {terminalstop}
\setinterfaceconstant {nonterminalstart} {nonterminalstart}
\setinterfaceconstant {nonterminalstop} {nonterminalstop}
\setinterfaceconstant {is} {is}
\setinterfacevariable {bnfgrammar} {bnfgrammar}
\setinterfacevariable {bnfgrammars} {bnfgrammars}
\stopinterface
\installnamespace{bnfgrammar}
\installcommandhandler \????bnfgrammar {bnfgrammar} \????bnfgrammar
\unexpanded\def\bnf_grammar_non_terminal#1>%
{\bnfgrammarparameter{\c!nonterminalstart}#1\/\bnfgrammarparameter{\c!nonterminalstop}}
\bgroup
\catcode`:\activecatcode
\unexpanded\gdef:{\bnfgrammarparameter{\c!is}}
\catcode`|\activecatcode
\unexpanded\gdef|{\bnfgrammarparameter{\c!option}}
\catcode`"\activecatcode
\unexpanded\gdef"%
{\thinspace\bgroup\bnfgrammarparameter{\c!terminalstart}%
\unexpanded\def"{\bnfgrammarparameter{\c!terminalstop}\egroup\thinspace}}
\catcode`'\activecatcode
\unexpanded\gdef'%
{\thinspace\bgroup\bnfgrammarparameter{\c!terminalstart}%
\unexpanded\def'{\bnfgrammarparameter{\c!terminalstop}\egroup\thinspace}}
\catcode`<\activecatcode
\global\let<=\bnf_grammar_non_terminal
\unexpanded\gdef\bnf_grammar_rule<#1>{\endgraf<#1>}
\egroup
\unexpanded\def\bnf_grammar_line
{\futurelet\next\bnf_grammar_switch}
\unexpanded\def\bnf_grammar_cont
{\endgraf\qquad}
\unexpanded\def\bnf_grammar_switch
{\ifx\next\bnf_grammar_non_terminal
\let\next=\bnf_grammar_rule
\else\expandafter\ifx\expandafter\next\csname stop\currentbnfgrammar\endcsname
\let\next=\relax
\else
\let\next=\bnf_grammar_cont
\fi\fi
\next}
\unexpanded\def\bnf_grammar_start%
{\dodoubleempty\bnf_grammar_start_indeed}
\unexpanded\def\bnf_grammar_start_indeed[#1][#2]%
{\begingroup
\edef\currentbnfgrammar{#1}
\setupcurrentbnfgrammar[#2]
\catcode`:\activecatcode
\catcode`|\activecatcode
\catcode`"\activecatcode
\catcode`'\activecatcode
\catcode`<\activecatcode
\let\par=\bnf_grammar_line
\obeylines}
\unexpanded\def\bnf_grammar_stop
{\endgroup
\blank
\checknextindentation[\bnfgrammarparameter{\c!indentnext}]}
\appendtoks
\setuevalue{start\currentbnfgrammar}{\bnf_grammar_start[\currentbnfgrammar]}%
\setuevalue{stop\currentbnfgrammar}{\bnf_grammar_stop}%
\to \everydefinebnfgrammar
\setupbnfgrammar
[\c!terminalstart=\tttf,
\c!terminalstop=,
\c!nonterminalstart=\mathematics{\langle},
\c!nonterminalstop=\mathematics{\rangle},
\c!is={ \mathematics{\longrightarrow}},
\c!option=\mathematics{\vert},
\c!indentnext=\v!no]
\definebnfgrammar
[\v!bnfgrammar]
\logo[BNF]{BNF}
\setuplabeltext[\s!en][\v!bnfgrammar=\BNF\ Grammar ]
\definefloat
[\v!bnfgrammar]
[\v!bnfgrammars]
\protect
\stopmodule
例子:
\usemodule[bnf-mkiv]
\starttext
\startplacebnfgrammar[title={An example of a placed grammar.}]
\startbnfgrammar[] % <-- empty brackets are important
<exp>: <num> | <num> "+" <num>
<num>: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
\stopbnfgrammar
\stopplacebnfgrammar
\stoptext