From c359e13d2e190476b96cb1e45f3c7136f3bea59f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 25 Dec 2021 20:30:24 +0100 Subject: [PATCH 1/7] Tex: add \renewcommand and \providecommand --- Units/parser-tex.r/newcommand.d/expected.tags | 2 ++ Units/parser-tex.r/newcommand.d/input.tex | 2 ++ parsers/tex.c | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/Units/parser-tex.r/newcommand.d/expected.tags b/Units/parser-tex.r/newcommand.d/expected.tags index 967ecb4b04..6f667472ba 100644 --- a/Units/parser-tex.r/newcommand.d/expected.tags +++ b/Units/parser-tex.r/newcommand.d/expected.tags @@ -1,3 +1,5 @@ +\\bar input.tex /^\\providecommand{\\bar}{\\section{#1}}$/;" C +\\foo input.tex /^\\renewcommand{\\foo}{\\section{#1}}$/;" C \\mysection0 input.tex /^\\newcommand{\\mysection0}{\\section{#1}}$/;" C \\mysection1 input.tex /^\\newcommand{\\mysection1}[1]{\\section{#1}}$/;" C \\mysection2 input.tex /^\\newcommand{\\mysection2}[1][1]{\\section{#1}}$/;" C diff --git a/Units/parser-tex.r/newcommand.d/input.tex b/Units/parser-tex.r/newcommand.d/input.tex index 13f01ee4ae..f9c1dbe068 100644 --- a/Units/parser-tex.r/newcommand.d/input.tex +++ b/Units/parser-tex.r/newcommand.d/input.tex @@ -2,6 +2,8 @@ \newcommand{\mysection0}{\section{#1}} \newcommand{\mysection1}[1]{\section{#1}} \newcommand{\mysection2}[1][1]{\section{#1}} +\renewcommand{\foo}{\section{#1}} +\providecommand{\bar}{\section{#1}} \begin{document} \mysection0{ABC} \mysection1{EFG} diff --git a/parsers/tex.c b/parsers/tex.c index 3de047795a..128da4a750 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -63,6 +63,8 @@ enum eKeywordId { KEYWORD_bibitem, KEYWORD_bibliography, KEYWORD_newcommand, + KEYWORD_renewcommand, + KEYWORD_providecommand, KEYWORD_newcounter, }; typedef int keywordId; /* to allow KEYWORD_NONE */ @@ -169,6 +171,8 @@ static const keywordTable TexKeywordTable [] = { { "bibitem", KEYWORD_bibitem }, { "bibliography", KEYWORD_bibliography }, { "newcommand", KEYWORD_newcommand }, + { "renewcommand", KEYWORD_renewcommand }, + { "providecommand", KEYWORD_providecommand }, { "newcounter", KEYWORD_newcounter }, }; @@ -934,6 +938,8 @@ static void parseTexFile (tokenInfo *const token) false, &tokenUnprocessed); break; case KEYWORD_newcommand: + case KEYWORD_renewcommand: + case KEYWORD_providecommand: eof = parseNewcommand (token, &tokenUnprocessed); break; case KEYWORD_newcounter: From 04d5c984c41a038fbf29e29f290d6412d1da506d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 25 Dec 2021 21:07:08 +0100 Subject: [PATCH 2/7] Tex: parse \def\cmd{replacement} --- Units/parser-tex.r/newcommand.d/expected.tags | 1 + Units/parser-tex.r/newcommand.d/input.tex | 1 + parsers/tex.c | 45 ++++++++++++++++++- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Units/parser-tex.r/newcommand.d/expected.tags b/Units/parser-tex.r/newcommand.d/expected.tags index 6f667472ba..f5187f2e9a 100644 --- a/Units/parser-tex.r/newcommand.d/expected.tags +++ b/Units/parser-tex.r/newcommand.d/expected.tags @@ -1,4 +1,5 @@ \\bar input.tex /^\\providecommand{\\bar}{\\section{#1}}$/;" C +\\baz input.tex /^\\def\\baz{\\section{#1}}$/;" C \\foo input.tex /^\\renewcommand{\\foo}{\\section{#1}}$/;" C \\mysection0 input.tex /^\\newcommand{\\mysection0}{\\section{#1}}$/;" C \\mysection1 input.tex /^\\newcommand{\\mysection1}[1]{\\section{#1}}$/;" C diff --git a/Units/parser-tex.r/newcommand.d/input.tex b/Units/parser-tex.r/newcommand.d/input.tex index f9c1dbe068..1be1b63946 100644 --- a/Units/parser-tex.r/newcommand.d/input.tex +++ b/Units/parser-tex.r/newcommand.d/input.tex @@ -4,6 +4,7 @@ \newcommand{\mysection2}[1][1]{\section{#1}} \renewcommand{\foo}{\section{#1}} \providecommand{\bar}{\section{#1}} +\def\baz{\section{#1}} \begin{document} \mysection0{ABC} \mysection1{EFG} diff --git a/parsers/tex.c b/parsers/tex.c index 128da4a750..7e21f5f921 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -65,6 +65,7 @@ enum eKeywordId { KEYWORD_newcommand, KEYWORD_renewcommand, KEYWORD_providecommand, + KEYWORD_def, KEYWORD_newcounter, }; typedef int keywordId; /* to allow KEYWORD_NONE */ @@ -173,6 +174,7 @@ static const keywordTable TexKeywordTable [] = { { "newcommand", KEYWORD_newcommand }, { "renewcommand", KEYWORD_renewcommand }, { "providecommand", KEYWORD_providecommand }, + { "def", KEYWORD_def }, { "newcounter", KEYWORD_newcounter }, }; @@ -606,13 +608,13 @@ static bool parseWithStrategy (tokenInfo *token, } else if (s->type == '*' && isType (token, '*')) next_token = true; - else if (s->type == '{' && isType (token, '{')) + else if ((s->type == '{' && isType (token, '{')) || (s->type == '\\' && isType (token, TOKEN_IDENTIFIER))) { int depth = 1; next_token = true; - if (!readToken (token)) + if (s->type == '{' && !readToken (token)) { eof = true; break; @@ -622,6 +624,11 @@ static bool parseWithStrategy (tokenInfo *token, copyToken (name, token); vStringClear (name->string); } + if (s->type == '\\') + { + vStringCat (name->string, token->string); + depth = 0; + } /* Handle the case the code like \section{} */ if (isType (token, '}')) @@ -845,6 +852,37 @@ static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed) return eof; } +static bool parseDef (tokenInfo *const token, bool *tokenUnprocessed) +{ + bool eof = false; + + /* \def\cmd{replacement} */ + struct TexParseStrategy strategy [] = { + { + .type = '\\', + .flags = 0, + .kindIndex = TEXTAG_COMMAND, + .roleIndex = ROLE_DEFINITION_INDEX, + .name = NULL, + .unique = false, + }, + { + .type = '{', + .flags = 0, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = 0 + } + }; + + if (parseWithStrategy (token, strategy, tokenUnprocessed)) + eof = true; + + return eof; +} + static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed) { bool eof = false; @@ -942,6 +980,9 @@ static void parseTexFile (tokenInfo *const token) case KEYWORD_providecommand: eof = parseNewcommand (token, &tokenUnprocessed); break; + case KEYWORD_def: + eof = parseDef (token, &tokenUnprocessed); + break; case KEYWORD_newcounter: eof = parseNewcounter (token, &tokenUnprocessed); break; From 952983db09f1e42a115b4377166eb6221abe1485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 25 Dec 2021 21:21:56 +0100 Subject: [PATCH 3/7] Tex: Parse \DeclareMathOperator{cmd}{def} --- Units/parser-tex.r/newcommand.d/expected.tags | 1 + Units/parser-tex.r/newcommand.d/input.tex | 1 + parsers/tex.c | 16 ++++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Units/parser-tex.r/newcommand.d/expected.tags b/Units/parser-tex.r/newcommand.d/expected.tags index f5187f2e9a..22ffcf4921 100644 --- a/Units/parser-tex.r/newcommand.d/expected.tags +++ b/Units/parser-tex.r/newcommand.d/expected.tags @@ -4,3 +4,4 @@ \\mysection0 input.tex /^\\newcommand{\\mysection0}{\\section{#1}}$/;" C \\mysection1 input.tex /^\\newcommand{\\mysection1}[1]{\\section{#1}}$/;" C \\mysection2 input.tex /^\\newcommand{\\mysection2}[1][1]{\\section{#1}}$/;" C +\\op input.tex /^\\DeclareMathOperator{\\op}{foo}$/;" o diff --git a/Units/parser-tex.r/newcommand.d/input.tex b/Units/parser-tex.r/newcommand.d/input.tex index 1be1b63946..4280ec5c7c 100644 --- a/Units/parser-tex.r/newcommand.d/input.tex +++ b/Units/parser-tex.r/newcommand.d/input.tex @@ -5,6 +5,7 @@ \renewcommand{\foo}{\section{#1}} \providecommand{\bar}{\section{#1}} \def\baz{\section{#1}} +\DeclareMathOperator{\op}{foo} \begin{document} \mysection0{ABC} \mysection1{EFG} diff --git a/parsers/tex.c b/parsers/tex.c index 7e21f5f921..f835e70b06 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -66,6 +66,7 @@ enum eKeywordId { KEYWORD_renewcommand, KEYWORD_providecommand, KEYWORD_def, + KEYWORD_declaremathoperator, KEYWORD_newcounter, }; typedef int keywordId; /* to allow KEYWORD_NONE */ @@ -120,6 +121,7 @@ typedef enum { TEXTAG_XINPUT, TEXTAG_BIBITEM, TEXTAG_COMMAND, + TEXTAG_OPERATOR, TEXTAG_COUNTER, TEXTAG_COUNT } texKind; @@ -152,6 +154,7 @@ static kindDefinition TexKinds [] = { .referenceOnly = true, ATTACH_ROLES(TexInputRoles) }, { true, 'B', "bibitem", "bibliography items" }, { true, 'C', "command", "command created with \\newcommand" }, + { true, 'o', "operator", "math operator created with \\DeclareMathOperator" }, { true, 'N', "counter", "counter created with \\newcounter" }, }; @@ -175,6 +178,7 @@ static const keywordTable TexKeywordTable [] = { { "renewcommand", KEYWORD_renewcommand }, { "providecommand", KEYWORD_providecommand }, { "def", KEYWORD_def }, + { "DeclareMathOperator", KEYWORD_declaremathoperator }, { "newcounter", KEYWORD_newcounter }, }; @@ -809,7 +813,7 @@ static bool parseEnv (tokenInfo *const token, bool begin, bool *tokenUnprocessed } -static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed) +static bool parseNewcommandFull (tokenInfo *const token, bool *tokenUnprocessed, texKind kind) { bool eof = false; @@ -818,7 +822,7 @@ static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed) { .type = '{', .flags = 0, - .kindIndex = TEXTAG_COMMAND, + .kindIndex = kind, .roleIndex = ROLE_DEFINITION_INDEX, .name = NULL, .unique = false, @@ -852,6 +856,11 @@ static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed) return eof; } +static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed) +{ + return parseNewcommandFull (token, tokenUnprocessed, TEXTAG_COMMAND); +} + static bool parseDef (tokenInfo *const token, bool *tokenUnprocessed) { bool eof = false; @@ -983,6 +992,9 @@ static void parseTexFile (tokenInfo *const token) case KEYWORD_def: eof = parseDef (token, &tokenUnprocessed); break; + case KEYWORD_declaremathoperator: + eof = parseNewcommandFull (token, &tokenUnprocessed, TEXTAG_OPERATOR); + break; case KEYWORD_newcounter: eof = parseNewcounter (token, &tokenUnprocessed); break; From bcf90edd155b51a6c2cdf73df09b1d3e7d20a87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 25 Dec 2021 21:54:45 +0100 Subject: [PATCH 4/7] Tex: parse \newenvironment and \renewenvironment --- .../newenvironment.d/expected.tags | 2 + Units/parser-tex.r/newenvironment.d/input.tex | 29 ++++++++++ parsers/tex.c | 53 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 Units/parser-tex.r/newenvironment.d/expected.tags create mode 100644 Units/parser-tex.r/newenvironment.d/input.tex diff --git a/Units/parser-tex.r/newenvironment.d/expected.tags b/Units/parser-tex.r/newenvironment.d/expected.tags new file mode 100644 index 0000000000..6a1258a0e2 --- /dev/null +++ b/Units/parser-tex.r/newenvironment.d/expected.tags @@ -0,0 +1,2 @@ +boxed input.tex /^\\newenvironment{boxed}$/;" e +boxedA input.tex /^\\renewenvironment{boxedA}$/;" e diff --git a/Units/parser-tex.r/newenvironment.d/input.tex b/Units/parser-tex.r/newenvironment.d/input.tex new file mode 100644 index 0000000000..62f0b2f625 --- /dev/null +++ b/Units/parser-tex.r/newenvironment.d/input.tex @@ -0,0 +1,29 @@ +\documentclass{article} +\newenvironment{boxed} + {\begin{center} + \begin{tabular}{|p{0.9\textwidth}|} + \hline\\ + } + { + \\\\\hline + \end{tabular} + \end{center} + } +\renewenvironment{boxedA} + {\begin{center} + \begin{tabular}{|p{0.9\textwidth}|} + \hline\\ + } + { + \\\\\hline + \end{tabular} + \end{center} + } +\begin{document} +\begin{boxed} +foo +\end{boxed} +\begin{boxedA} +foo +\end{boxedA} +\end{document} \ No newline at end of file diff --git a/parsers/tex.c b/parsers/tex.c index f835e70b06..1e2e4a6f13 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -67,6 +67,8 @@ enum eKeywordId { KEYWORD_providecommand, KEYWORD_def, KEYWORD_declaremathoperator, + KEYWORD_newenvironment, + KEYWORD_renewenvironment, KEYWORD_newcounter, }; typedef int keywordId; /* to allow KEYWORD_NONE */ @@ -122,6 +124,7 @@ typedef enum { TEXTAG_BIBITEM, TEXTAG_COMMAND, TEXTAG_OPERATOR, + TEXTAG_ENVIRONMENT, TEXTAG_COUNTER, TEXTAG_COUNT } texKind; @@ -155,6 +158,7 @@ static kindDefinition TexKinds [] = { { true, 'B', "bibitem", "bibliography items" }, { true, 'C', "command", "command created with \\newcommand" }, { true, 'o', "operator", "math operator created with \\DeclareMathOperator" }, + { true, 'e', "environment", "environment created with \\newenvironment" }, { true, 'N', "counter", "counter created with \\newcounter" }, }; @@ -179,6 +183,8 @@ static const keywordTable TexKeywordTable [] = { { "providecommand", KEYWORD_providecommand }, { "def", KEYWORD_def }, { "DeclareMathOperator", KEYWORD_declaremathoperator }, + { "newenvironment", KEYWORD_newenvironment }, + { "renewenvironment", KEYWORD_renewenvironment}, { "newcounter", KEYWORD_newcounter }, }; @@ -892,6 +898,48 @@ static bool parseDef (tokenInfo *const token, bool *tokenUnprocessed) return eof; } +static bool parseNewEnvironment (tokenInfo *const token, bool *tokenUnprocessed) +{ + bool eof = false; + /* \newenvironment{nam}[args]{begdef}{enddef} */ + struct TexParseStrategy strategy [] = { + { + .type = '{', + .flags = 0, + .kindIndex = TEXTAG_ENVIRONMENT, + .roleIndex = ROLE_DEFINITION_INDEX, + .name = NULL, + .unique = false, + }, + { + .type = '[', + .flags = TEX_NAME_FLAG_OPTIONAL, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = '{', + .flags = 0, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = '{', + .flags = 0, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = 0 + } + }; + + if (parseWithStrategy (token, strategy, tokenUnprocessed)) + eof = true; + + return eof; +} + static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed) { bool eof = false; @@ -921,6 +969,7 @@ static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed) return eof; } + static void parseTexFile (tokenInfo *const token) { bool eof = false; @@ -995,6 +1044,10 @@ static void parseTexFile (tokenInfo *const token) case KEYWORD_declaremathoperator: eof = parseNewcommandFull (token, &tokenUnprocessed, TEXTAG_OPERATOR); break; + case KEYWORD_newenvironment: + case KEYWORD_renewenvironment: + eof = parseNewEnvironment (token, &tokenUnprocessed); + break; case KEYWORD_newcounter: eof = parseNewcounter (token, &tokenUnprocessed); break; From aa63a3eaaa50adaa9ed216711357106a31a1682f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Sat, 25 Dec 2021 22:41:36 +0100 Subject: [PATCH 5/7] Tex: parse \newtheorem --- .../newenvironment.d/expected.tags | 1 + Units/parser-tex.r/newenvironment.d/input.tex | 4 ++ parsers/tex.c | 51 +++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/Units/parser-tex.r/newenvironment.d/expected.tags b/Units/parser-tex.r/newenvironment.d/expected.tags index 6a1258a0e2..6cd4f41c25 100644 --- a/Units/parser-tex.r/newenvironment.d/expected.tags +++ b/Units/parser-tex.r/newenvironment.d/expected.tags @@ -1,2 +1,3 @@ boxed input.tex /^\\newenvironment{boxed}$/;" e boxedA input.tex /^\\renewenvironment{boxedA}$/;" e +theorem input.tex /^\\newtheorem{theorem}{Theorem}$/;" t diff --git a/Units/parser-tex.r/newenvironment.d/input.tex b/Units/parser-tex.r/newenvironment.d/input.tex index 62f0b2f625..06c8877fff 100644 --- a/Units/parser-tex.r/newenvironment.d/input.tex +++ b/Units/parser-tex.r/newenvironment.d/input.tex @@ -19,6 +19,7 @@ \end{tabular} \end{center} } +\newtheorem{theorem}{Theorem} \begin{document} \begin{boxed} foo @@ -26,4 +27,7 @@ \begin{boxedA} foo \end{boxedA} +\begin{theorem} +bar +\end{theorem} \end{document} \ No newline at end of file diff --git a/parsers/tex.c b/parsers/tex.c index 1e2e4a6f13..c2f9161111 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -69,6 +69,7 @@ enum eKeywordId { KEYWORD_declaremathoperator, KEYWORD_newenvironment, KEYWORD_renewenvironment, + KEYWORD_newtheorem, KEYWORD_newcounter, }; typedef int keywordId; /* to allow KEYWORD_NONE */ @@ -125,6 +126,7 @@ typedef enum { TEXTAG_COMMAND, TEXTAG_OPERATOR, TEXTAG_ENVIRONMENT, + TEXTAG_THEOREM, TEXTAG_COUNTER, TEXTAG_COUNT } texKind; @@ -159,6 +161,7 @@ static kindDefinition TexKinds [] = { { true, 'C', "command", "command created with \\newcommand" }, { true, 'o', "operator", "math operator created with \\DeclareMathOperator" }, { true, 'e', "environment", "environment created with \\newenvironment" }, + { true, 't', "theorem", "theorem created with \\newtheorem" }, { true, 'N', "counter", "counter created with \\newcounter" }, }; @@ -185,6 +188,7 @@ static const keywordTable TexKeywordTable [] = { { "DeclareMathOperator", KEYWORD_declaremathoperator }, { "newenvironment", KEYWORD_newenvironment }, { "renewenvironment", KEYWORD_renewenvironment}, + { "newtheorem", KEYWORD_newtheorem }, { "newcounter", KEYWORD_newcounter }, }; @@ -940,6 +944,50 @@ static bool parseNewEnvironment (tokenInfo *const token, bool *tokenUnprocessed) return eof; } +static bool parseNewTheorem (tokenInfo *const token, bool *tokenUnprocessed) +{ + bool eof = false; + /* \newtheorem{name}{title} + \newtheorem{name}{title}[numbered_within] + \newtheorem{name}[numbered_like]{title} */ + struct TexParseStrategy strategy [] = { + { + .type = '{', + .flags = 0, + .kindIndex = TEXTAG_THEOREM, + .roleIndex = ROLE_DEFINITION_INDEX, + .name = NULL, + .unique = false, + }, + { + .type = '[', + .flags = TEX_NAME_FLAG_OPTIONAL, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = '{', + .flags = 0, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = '[', + .flags = TEX_NAME_FLAG_OPTIONAL, + .kindIndex = KIND_GHOST_INDEX, + .name = NULL, + }, + { + .type = 0 + } + }; + + if (parseWithStrategy (token, strategy, tokenUnprocessed)) + eof = true; + + return eof; +} + static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed) { bool eof = false; @@ -1048,6 +1096,9 @@ static void parseTexFile (tokenInfo *const token) case KEYWORD_renewenvironment: eof = parseNewEnvironment (token, &tokenUnprocessed); break; + case KEYWORD_newtheorem: + eof = parseNewTheorem (token, &tokenUnprocessed); + break; case KEYWORD_newcounter: eof = parseNewcounter (token, &tokenUnprocessed); break; From af6af4ddc29a013a1d49a735b02f23e96ef9d9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Mon, 27 Dec 2021 23:00:32 +0100 Subject: [PATCH 6/7] Tex: Fix TEX_NAME_FLAG_OPTIONAL for the last macro parameter When the last parameter is optional and not present, the token is already read by parseWithStrategy() but this token is not reported to the caller as unprocessed which may cause missed tag for the following macro. --- Units/parser-tex.r/newenvironment.d/expected.tags | 1 + Units/parser-tex.r/newenvironment.d/input.tex | 1 + parsers/tex.c | 8 ++++++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Units/parser-tex.r/newenvironment.d/expected.tags b/Units/parser-tex.r/newenvironment.d/expected.tags index 6cd4f41c25..20b2896922 100644 --- a/Units/parser-tex.r/newenvironment.d/expected.tags +++ b/Units/parser-tex.r/newenvironment.d/expected.tags @@ -1,3 +1,4 @@ boxed input.tex /^\\newenvironment{boxed}$/;" e boxedA input.tex /^\\renewenvironment{boxedA}$/;" e theorem input.tex /^\\newtheorem{theorem}{Theorem}$/;" t +theoremA input.tex /^\\newtheorem{theoremA}{Theorem A}$/;" t diff --git a/Units/parser-tex.r/newenvironment.d/input.tex b/Units/parser-tex.r/newenvironment.d/input.tex index 06c8877fff..0cd6ddfe89 100644 --- a/Units/parser-tex.r/newenvironment.d/input.tex +++ b/Units/parser-tex.r/newenvironment.d/input.tex @@ -1,4 +1,5 @@ \documentclass{article} +\newtheorem{theoremA}{Theorem A} \newenvironment{boxed} {\begin{center} \begin{tabular}{|p{0.9\textwidth}|} diff --git a/parsers/tex.c b/parsers/tex.c index c2f9161111..8e810d8471 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -693,6 +693,10 @@ static bool parseWithStrategy (tokenInfo *token, } } + /* The last token is optional and not present - let the caller know */ + if (!next_token) + *tokenUnprocessed = true; + if (name) deleteToken (name); @@ -991,7 +995,7 @@ static bool parseNewTheorem (tokenInfo *const token, bool *tokenUnprocessed) static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed) { bool eof = false; - /* \newccounter {counter}[parentCounter] */ + /* \newcounter {counter}[parentCounter] */ struct TexParseStrategy strategy [] = { { .type = '{', @@ -1003,7 +1007,7 @@ static bool parseNewcounter (tokenInfo *const token, bool *tokenUnprocessed) }, { .type = '[', - .flags = 0, + .flags = TEX_NAME_FLAG_OPTIONAL, .kindIndex = KIND_GHOST_INDEX, .name = NULL, }, From c6cbaf9cc4b7fccde7384e99bcb8b042e03021ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Tue, 28 Dec 2021 18:22:29 +0100 Subject: [PATCH 7/7] Tex: Allow omitting {} for some macros Macros like \newcommand can be written both as \newcommand{\foo}{bar} and \newcommand\foo{bar} Unify \def parsing and \newcommand parsing so that when strategy type is defined as '\\', the {} pair may or may not be present. --- Units/parser-tex.r/newcommand.d/expected.tags | 1 + Units/parser-tex.r/newcommand.d/input.tex | 1 + parsers/tex.c | 49 ++++--------------- parsers/tex.h | 4 +- 4 files changed, 14 insertions(+), 41 deletions(-) diff --git a/Units/parser-tex.r/newcommand.d/expected.tags b/Units/parser-tex.r/newcommand.d/expected.tags index 22ffcf4921..41e4bd75e3 100644 --- a/Units/parser-tex.r/newcommand.d/expected.tags +++ b/Units/parser-tex.r/newcommand.d/expected.tags @@ -4,4 +4,5 @@ \\mysection0 input.tex /^\\newcommand{\\mysection0}{\\section{#1}}$/;" C \\mysection1 input.tex /^\\newcommand{\\mysection1}[1]{\\section{#1}}$/;" C \\mysection2 input.tex /^\\newcommand{\\mysection2}[1][1]{\\section{#1}}$/;" C +\\mysection3 input.tex /^\\newcommand\\mysection3[1][1]{\\section{#1}}$/;" C \\op input.tex /^\\DeclareMathOperator{\\op}{foo}$/;" o diff --git a/Units/parser-tex.r/newcommand.d/input.tex b/Units/parser-tex.r/newcommand.d/input.tex index 4280ec5c7c..6923b40f50 100644 --- a/Units/parser-tex.r/newcommand.d/input.tex +++ b/Units/parser-tex.r/newcommand.d/input.tex @@ -2,6 +2,7 @@ \newcommand{\mysection0}{\section{#1}} \newcommand{\mysection1}[1]{\section{#1}} \newcommand{\mysection2}[1][1]{\section{#1}} +\newcommand\mysection3[1][1]{\section{#1}} \renewcommand{\foo}{\section{#1}} \providecommand{\bar}{\section{#1}} \def\baz{\section{#1}} diff --git a/parsers/tex.c b/parsers/tex.c index 8e810d8471..25f219a4f9 100644 --- a/parsers/tex.c +++ b/parsers/tex.c @@ -622,13 +622,15 @@ static bool parseWithStrategy (tokenInfo *token, } else if (s->type == '*' && isType (token, '*')) next_token = true; - else if ((s->type == '{' && isType (token, '{')) || (s->type == '\\' && isType (token, TOKEN_IDENTIFIER))) + else if (((s->type == '{' || s->type == '\\') && isType (token, '{')) || + (s->type == '\\' && isType (token, TOKEN_IDENTIFIER))) { int depth = 1; + bool missing_parens = isType (token, TOKEN_IDENTIFIER); next_token = true; - if (s->type == '{' && !readToken (token)) + if (!missing_parens && !readToken (token)) { eof = true; break; @@ -638,7 +640,7 @@ static bool parseWithStrategy (tokenInfo *token, copyToken (name, token); vStringClear (name->string); } - if (s->type == '\\') + if (missing_parens) { vStringCat (name->string, token->string); depth = 0; @@ -831,10 +833,12 @@ static bool parseNewcommandFull (tokenInfo *const token, bool *tokenUnprocessed, { bool eof = false; - /* \newcommand {cmd}[args][opt]{def} */ + /* \newcommand{cmd}[args][opt]{def} */ + /* \newcommand\cmd[args][opt]{def} */ + /* \def\cmd{replacement} */ struct TexParseStrategy strategy [] = { { - .type = '{', + .type = '\\', .flags = 0, .kindIndex = kind, .roleIndex = ROLE_DEFINITION_INDEX, @@ -875,37 +879,6 @@ static bool parseNewcommand (tokenInfo *const token, bool *tokenUnprocessed) return parseNewcommandFull (token, tokenUnprocessed, TEXTAG_COMMAND); } -static bool parseDef (tokenInfo *const token, bool *tokenUnprocessed) -{ - bool eof = false; - - /* \def\cmd{replacement} */ - struct TexParseStrategy strategy [] = { - { - .type = '\\', - .flags = 0, - .kindIndex = TEXTAG_COMMAND, - .roleIndex = ROLE_DEFINITION_INDEX, - .name = NULL, - .unique = false, - }, - { - .type = '{', - .flags = 0, - .kindIndex = KIND_GHOST_INDEX, - .name = NULL, - }, - { - .type = 0 - } - }; - - if (parseWithStrategy (token, strategy, tokenUnprocessed)) - eof = true; - - return eof; -} - static bool parseNewEnvironment (tokenInfo *const token, bool *tokenUnprocessed) { bool eof = false; @@ -1088,10 +1061,8 @@ static void parseTexFile (tokenInfo *const token) case KEYWORD_newcommand: case KEYWORD_renewcommand: case KEYWORD_providecommand: - eof = parseNewcommand (token, &tokenUnprocessed); - break; case KEYWORD_def: - eof = parseDef (token, &tokenUnprocessed); + eof = parseNewcommand (token, &tokenUnprocessed); break; case KEYWORD_declaremathoperator: eof = parseNewcommandFull (token, &tokenUnprocessed, TEXTAG_OPERATOR); diff --git a/parsers/tex.h b/parsers/tex.h index b60b55bcc9..b5a9d8b9b2 100644 --- a/parsers/tex.h +++ b/parsers/tex.h @@ -42,8 +42,8 @@ enum TexNameFlag { }; struct TexParseStrategy { - /* Expected token type '<', '[', '*', and '{' are supported. - * 0 means the end of strategies. + /* Expected token type '<', '[', '*', '{', and '\\' are supported. + * 0 means the end of strategies. '\\' means {} pair may be omitted. * * A string between <>, [], or {} (pairs) can be tagged or store to * a vString. See kindIndex and name field of this structure.