Bug? LaTeX misparses nested optional arguments
LaTeX seems to be having problems handling nested optional arguments. I've included a minimal code example that generates the error:
documentclass[12pt,oneside]{book}
begin{document}
newcommand{termbad}[2]{#2#1}
newcommand{termgood}[2]{#2#1}
newcommand{up}[1]{#1}
newcommand{dd}[1]{#1}
termgood{up{Tart}}{Pop}
termbad[up{Tart}]{Pop}
termgood{dd[Tart]}{Pop}
termbad[{dd[Tart]}]{Pop}
%termbad[dd[Tart]]{Pop}
end{document}
If you run this code, it works. If you remove the %
in the second to last line, it fails with:
Runaway argument?
Tart{Pop} par par end {document}
!File ended while scanning use of dd.
After further tinkering, I have discovered the problem: LaTeX is reading the ]
for the inner optional argument as the end of the outer optional argument and then passing a malformed argument in. So it is passing in dd[Tart
as the optional argument to termbad
instead of dd[Tart]
.
This still feels like a bug to me. Nesting braces in arguments works, brackets should as well. The following are workarounds:
Enclose the inner optional argument in braces (as in the line before
%
).Redefine your inner function to require its argument instead of using optional arguments.
Redefine your outer function to require its argument instead of using optional arguments.
Any one of the three works around the issue.
(Reposted here; question was originally posted to stackexchange and then closed instead of being migrated.)
nesting optional-arguments
add a comment |
LaTeX seems to be having problems handling nested optional arguments. I've included a minimal code example that generates the error:
documentclass[12pt,oneside]{book}
begin{document}
newcommand{termbad}[2]{#2#1}
newcommand{termgood}[2]{#2#1}
newcommand{up}[1]{#1}
newcommand{dd}[1]{#1}
termgood{up{Tart}}{Pop}
termbad[up{Tart}]{Pop}
termgood{dd[Tart]}{Pop}
termbad[{dd[Tart]}]{Pop}
%termbad[dd[Tart]]{Pop}
end{document}
If you run this code, it works. If you remove the %
in the second to last line, it fails with:
Runaway argument?
Tart{Pop} par par end {document}
!File ended while scanning use of dd.
After further tinkering, I have discovered the problem: LaTeX is reading the ]
for the inner optional argument as the end of the outer optional argument and then passing a malformed argument in. So it is passing in dd[Tart
as the optional argument to termbad
instead of dd[Tart]
.
This still feels like a bug to me. Nesting braces in arguments works, brackets should as well. The following are workarounds:
Enclose the inner optional argument in braces (as in the line before
%
).Redefine your inner function to require its argument instead of using optional arguments.
Redefine your outer function to require its argument instead of using optional arguments.
Any one of the three works around the issue.
(Reposted here; question was originally posted to stackexchange and then closed instead of being migrated.)
nesting optional-arguments
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics.
– user10274
Oct 20 '12 at 11:57
add a comment |
LaTeX seems to be having problems handling nested optional arguments. I've included a minimal code example that generates the error:
documentclass[12pt,oneside]{book}
begin{document}
newcommand{termbad}[2]{#2#1}
newcommand{termgood}[2]{#2#1}
newcommand{up}[1]{#1}
newcommand{dd}[1]{#1}
termgood{up{Tart}}{Pop}
termbad[up{Tart}]{Pop}
termgood{dd[Tart]}{Pop}
termbad[{dd[Tart]}]{Pop}
%termbad[dd[Tart]]{Pop}
end{document}
If you run this code, it works. If you remove the %
in the second to last line, it fails with:
Runaway argument?
Tart{Pop} par par end {document}
!File ended while scanning use of dd.
After further tinkering, I have discovered the problem: LaTeX is reading the ]
for the inner optional argument as the end of the outer optional argument and then passing a malformed argument in. So it is passing in dd[Tart
as the optional argument to termbad
instead of dd[Tart]
.
This still feels like a bug to me. Nesting braces in arguments works, brackets should as well. The following are workarounds:
Enclose the inner optional argument in braces (as in the line before
%
).Redefine your inner function to require its argument instead of using optional arguments.
Redefine your outer function to require its argument instead of using optional arguments.
Any one of the three works around the issue.
(Reposted here; question was originally posted to stackexchange and then closed instead of being migrated.)
nesting optional-arguments
LaTeX seems to be having problems handling nested optional arguments. I've included a minimal code example that generates the error:
documentclass[12pt,oneside]{book}
begin{document}
newcommand{termbad}[2]{#2#1}
newcommand{termgood}[2]{#2#1}
newcommand{up}[1]{#1}
newcommand{dd}[1]{#1}
termgood{up{Tart}}{Pop}
termbad[up{Tart}]{Pop}
termgood{dd[Tart]}{Pop}
termbad[{dd[Tart]}]{Pop}
%termbad[dd[Tart]]{Pop}
end{document}
If you run this code, it works. If you remove the %
in the second to last line, it fails with:
Runaway argument?
Tart{Pop} par par end {document}
!File ended while scanning use of dd.
After further tinkering, I have discovered the problem: LaTeX is reading the ]
for the inner optional argument as the end of the outer optional argument and then passing a malformed argument in. So it is passing in dd[Tart
as the optional argument to termbad
instead of dd[Tart]
.
This still feels like a bug to me. Nesting braces in arguments works, brackets should as well. The following are workarounds:
Enclose the inner optional argument in braces (as in the line before
%
).Redefine your inner function to require its argument instead of using optional arguments.
Redefine your outer function to require its argument instead of using optional arguments.
Any one of the three works around the issue.
(Reposted here; question was originally posted to stackexchange and then closed instead of being migrated.)
nesting optional-arguments
nesting optional-arguments
edited Oct 20 '12 at 12:35
Kurt
36.4k847162
36.4k847162
asked Oct 20 '12 at 11:07
JKreftJKreft
260211
260211
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics.
– user10274
Oct 20 '12 at 11:57
add a comment |
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics.
– user10274
Oct 20 '12 at 11:57
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics.
– user10274
Oct 20 '12 at 11:57
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics.
– user10274
Oct 20 '12 at 11:57
add a comment |
1 Answer
1
active
oldest
votes
When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ]
that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:
foo[{bar[...]}]{...}
It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:
deffoo#1#2{bar[#1]{#2}}
This should be
deffoo#1#2{bar[{#1}]{#2}}
Then #1
may contain square brackets, especially ]
.
7
Worth noting thatxparse
-defined functions do not suffer from this
– Joseph Wright♦
Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
2
an answer explicitly showing howxparse
is used has been posted at How do I nest a command with an optional argument?
– barbara beeton
Apr 15 '16 at 15:55
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f78414%2fbug-latex-misparses-nested-optional-arguments%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ]
that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:
foo[{bar[...]}]{...}
It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:
deffoo#1#2{bar[#1]{#2}}
This should be
deffoo#1#2{bar[{#1}]{#2}}
Then #1
may contain square brackets, especially ]
.
7
Worth noting thatxparse
-defined functions do not suffer from this
– Joseph Wright♦
Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
2
an answer explicitly showing howxparse
is used has been posted at How do I nest a command with an optional argument?
– barbara beeton
Apr 15 '16 at 15:55
add a comment |
When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ]
that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:
foo[{bar[...]}]{...}
It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:
deffoo#1#2{bar[#1]{#2}}
This should be
deffoo#1#2{bar[{#1}]{#2}}
Then #1
may contain square brackets, especially ]
.
7
Worth noting thatxparse
-defined functions do not suffer from this
– Joseph Wright♦
Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
2
an answer explicitly showing howxparse
is used has been posted at How do I nest a command with an optional argument?
– barbara beeton
Apr 15 '16 at 15:55
add a comment |
When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ]
that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:
foo[{bar[...]}]{...}
It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:
deffoo#1#2{bar[#1]{#2}}
This should be
deffoo#1#2{bar[{#1}]{#2}}
Then #1
may contain square brackets, especially ]
.
When TeX reads arguments, then TeX only checks for matching curly braces (characters with catcode 1 and 2). Square brackets are not special in this sense. The first ]
that is not hidden inside curly braces is taken as the end of the optional argument. Therefore an additional set of braces is the usual solution:
foo[{bar[...]}]{...}
It is only a bug, if this does not work, e.g. if the definition passes optional arguments to other commands:
deffoo#1#2{bar[#1]{#2}}
This should be
deffoo#1#2{bar[{#1}]{#2}}
Then #1
may contain square brackets, especially ]
.
answered Oct 20 '12 at 11:25
Heiko OberdiekHeiko Oberdiek
229k17555906
229k17555906
7
Worth noting thatxparse
-defined functions do not suffer from this
– Joseph Wright♦
Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
2
an answer explicitly showing howxparse
is used has been posted at How do I nest a command with an optional argument?
– barbara beeton
Apr 15 '16 at 15:55
add a comment |
7
Worth noting thatxparse
-defined functions do not suffer from this
– Joseph Wright♦
Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
2
an answer explicitly showing howxparse
is used has been posted at How do I nest a command with an optional argument?
– barbara beeton
Apr 15 '16 at 15:55
7
7
Worth noting that
xparse
-defined functions do not suffer from this– Joseph Wright♦
Oct 20 '12 at 11:41
Worth noting that
xparse
-defined functions do not suffer from this– Joseph Wright♦
Oct 20 '12 at 11:41
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
Thanks for the answers. I'm looking at xparse now, since I'm using some complex code to create a highly linked and formatted document. This may solve a few of the problems I've been having.
– JKreft
Oct 23 '12 at 12:33
2
2
an answer explicitly showing how
xparse
is used has been posted at How do I nest a command with an optional argument?– barbara beeton
Apr 15 '16 at 15:55
an answer explicitly showing how
xparse
is used has been posted at How do I nest a command with an optional argument?– barbara beeton
Apr 15 '16 at 15:55
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f78414%2fbug-latex-misparses-nested-optional-arguments%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
As far as I can see, the main problem is that LaTeX doesn't define the notion of nested optional arguments. This is why different implementations have different semantics.
– user10274
Oct 20 '12 at 11:57