Bug? LaTeX misparses nested optional arguments












16















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.)










share|improve this question

























  • 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
















16















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.)










share|improve this question

























  • 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














16












16








16


1






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.)










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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



















  • 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










1 Answer
1






active

oldest

votes


















23














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 ].






share|improve this answer



















  • 7





    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






  • 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











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
});


}
});














draft saved

draft discarded


















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









23














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 ].






share|improve this answer



















  • 7





    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






  • 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
















23














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 ].






share|improve this answer



















  • 7





    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






  • 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














23












23








23







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 ].






share|improve this answer













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 ].







share|improve this answer












share|improve this answer



share|improve this answer










answered Oct 20 '12 at 11:25









Heiko OberdiekHeiko Oberdiek

229k17555906




229k17555906








  • 7





    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






  • 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














  • 7





    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






  • 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








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


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

How to change which sound is reproduced for terminal bell?

Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

Can I use Tabulator js library in my java Spring + Thymeleaf project?