Skip to content

Commit fa73948

Browse files
author
hornik
committed
Fix PR#18855 issue 2. By Duncan Murdoch.
git-svn-id: https://svn.r-project.org/R/trunk@87714 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 5dad4a9 commit fa73948

File tree

5 files changed

+92
-145
lines changed

5 files changed

+92
-145
lines changed

doc/NEWS.Rd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,9 @@
565565
566566
\item The \code{tools::parseLatex()} parser made several parsing
567567
errors (\PR{18855}).
568+
569+
\item Error messages produced by \code{tools::parseLatex()} are
570+
now more readable (\PR{18855}).
568571
}
569572
}
570573
}

src/library/tools/R/parseLatex.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
# A copy of the GNU General Public License is available at
1717
# https://www.R-project.org/Licenses/
1818

19-
parseLatex <- function(text, filename = deparse1(substitute(text)),
19+
parseLatex <- function(text, filename = "text",
2020
verbose = FALSE, verbatim = c("verbatim", "verbatim*",
2121
"Sinput", "Soutput"),
2222
verb = "\\Sexpr")
2323
{
2424
## the internal function must get some sort of srcfile
25-
srcfile <- srcfilecopy(filename, text, file.mtime(filename))
25+
srcfile <- srcfilecopy(filename, text)
2626
text <- paste(text, collapse="\n")
2727
.External2(C_parseLatex, text, srcfile, verbose, as.character(verbatim), as.character(verb))
2828
}

src/library/tools/man/parseLatex.Rd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
characters.
1717
}
1818
\usage{
19-
parseLatex(text, filename = deparse1(substitute(text)),
19+
parseLatex(text, filename = "text",
2020
verbose = FALSE,
2121
verbatim = c("verbatim", "verbatim*",
2222
"Sinput", "Soutput"),
@@ -29,7 +29,7 @@ latexToUtf8(x)
2929
A character vector containing LaTeX source code.
3030
}
3131
\item{filename}{
32-
A filename to use in syntax error messages.
32+
No longer used.
3333
}
3434
\item{verbose}{
3535
If \code{TRUE}, print debug error messages.

src/library/tools/src/gramLatex.c

Lines changed: 44 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ struct ParseState {
201201

202202
static Rboolean busy = FALSE;
203203
static ParseState parseState;
204+
static char ParseErrorMsg[PARSE_ERROR_SIZE];
204205

205206
#define PRESERVE_SV(x) R_PreserveInMSet((x), parseState.mset)
206207
#define RELEASE_SV(x) R_ReleaseFromMSet((x), parseState.mset)
@@ -224,7 +225,7 @@ static int mkVerb2(const char *, int);
224225
static int mkVerbEnv(void);
225226
static int mkDollar(int);
226227

227-
static SEXP R_LatexTagSymbol = NULL;
228+
static SEXP LatexTagSymbol = NULL;
228229

229230
#define YYSTYPE SEXP
230231

@@ -746,9 +747,9 @@ static const yytype_int8 yytranslate[] =
746747
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
747748
static const yytype_uint8 yyrline[] =
748749
{
749-
0, 183, 183, 184, 185, 188, 189, 190, 191, 192,
750-
193, 195, 196, 198, 199, 200, 201, 202, 203, 204,
751-
205, 207, 211, 215, 219, 221, 223, 224
750+
0, 184, 184, 185, 186, 189, 190, 191, 192, 193,
751+
194, 196, 197, 199, 200, 201, 202, 203, 204, 205,
752+
206, 208, 212, 216, 220, 222, 224, 225
752753
};
753754
#endif
754755

@@ -2153,7 +2154,7 @@ static SEXP xxenv(SEXP begin, SEXP body, SEXP end, YYLTYPE *lloc)
21532154
RELEASE_SV(body);
21542155
}
21552156
setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, parseState.SrcFile));
2156-
setAttrib(ans, R_LatexTagSymbol, mkString("ENVIRONMENT"));
2157+
setAttrib(ans, LatexTagSymbol, mkString("ENVIRONMENT"));
21572158
if (!isNull(end))
21582159
RELEASE_SV(end);
21592160
#if DEBUGVALS
@@ -2171,7 +2172,7 @@ static SEXP xxmath(SEXP body, YYLTYPE *lloc, Rboolean display)
21712172
PRESERVE_SV(ans = PairToVectorList(CDR(body)));
21722173
RELEASE_SV(body);
21732174
setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, parseState.SrcFile));
2174-
setAttrib(ans, R_LatexTagSymbol,
2175+
setAttrib(ans, LatexTagSymbol,
21752176
mkString(display ? "DISPLAYMATH" : "MATH"));
21762177
#if DEBUGVALS
21772178
Rprintf(" result: %p\n", ans);
@@ -2192,7 +2193,7 @@ static SEXP xxblock(SEXP body, YYLTYPE *lloc)
21922193
RELEASE_SV(body);
21932194
}
21942195
setAttrib(ans, R_SrcrefSymbol, makeSrcref(lloc, parseState.SrcFile));
2195-
setAttrib(ans, R_LatexTagSymbol, mkString("BLOCK"));
2196+
setAttrib(ans, LatexTagSymbol, mkString("BLOCK"));
21962197

21972198
#if DEBUGVALS
21982199
Rprintf(" result: %p\n", ans);
@@ -2227,7 +2228,7 @@ static void xxsavevalue(SEXP items, YYLTYPE *lloc)
22272228
} else {
22282229
PRESERVE_SV(parseState.Value = allocVector(VECSXP, 1));
22292230
SET_VECTOR_ELT(parseState.Value, 0, ScalarString(mkChar("")));
2230-
setAttrib(VECTOR_ELT(parseState.Value, 0), R_LatexTagSymbol, mkString("TEXT"));
2231+
setAttrib(VECTOR_ELT(parseState.Value, 0), LatexTagSymbol, mkString("TEXT"));
22312232
}
22322233
if (!isNull(parseState.Value)) {
22332234
setAttrib(parseState.Value, R_ClassSymbol, mkString("LaTeX"));
@@ -2237,7 +2238,7 @@ static void xxsavevalue(SEXP items, YYLTYPE *lloc)
22372238

22382239
static SEXP xxtag(SEXP item, int type, YYLTYPE *lloc)
22392240
{
2240-
setAttrib(item, R_LatexTagSymbol, mkString(yytname[YYTRANSLATE(type)]));
2241+
setAttrib(item, LatexTagSymbol, mkString(yytname[YYTRANSLATE(type)]));
22412242
setAttrib(item, R_SrcrefSymbol, makeSrcref(lloc, parseState.SrcFile));
22422243
return item;
22432244
}
@@ -2278,10 +2279,7 @@ static int xxgetc(void)
22782279
prevcols[prevpos] = parseState.xxcolno;
22792280

22802281
if (c == EOF) return R_EOF;
2281-
2282-
R_ParseContextLast = (R_ParseContextLast + 1) % PARSE_CONTEXT_SIZE;
2283-
R_ParseContext[R_ParseContextLast] = (char) c;
2284-
2282+
22852283
if (c == '\n') {
22862284
parseState.xxlineno += 1;
22872285
parseState.xxcolno = 1;
@@ -2293,8 +2291,6 @@ static int xxgetc(void)
22932291

22942292
if (c == '\t') parseState.xxcolno = ((parseState.xxcolno + 6) & ~7) + 1;
22952293

2296-
R_ParseContextLine = parseState.xxlineno;
2297-
22982294
return c;
22992295
}
23002296

@@ -2306,12 +2302,6 @@ static int xxungetc(int c)
23062302
parseState.xxcolno = prevcols[prevpos];
23072303
prevpos = (prevpos + PUSHBACK_BUFSIZE - 1) % PUSHBACK_BUFSIZE;
23082304

2309-
R_ParseContextLine = parseState.xxlineno;
2310-
2311-
R_ParseContext[R_ParseContextLast] = '\0';
2312-
/* macOS requires us to keep this non-negative */
2313-
R_ParseContextLast = (R_ParseContextLast + PARSE_CONTEXT_SIZE - 1)
2314-
% PARSE_CONTEXT_SIZE;
23152305
if(npush >= PUSHBACK_BUFSIZE - 2) return R_EOF;
23162306
pushback[npush++] = c;
23172307
return c;
@@ -2402,18 +2392,9 @@ static void UseState(ParseState *state) {
24022392
parseState.prevState = state->prevState;
24032393
}
24042394

2405-
static void InitSymbols(void)
2406-
{
2407-
if (!R_LatexTagSymbol)
2408-
R_LatexTagSymbol = install("latex_tag");
2409-
}
2410-
24112395
static SEXP ParseLatex(ParseStatus *status, SEXP srcfile)
24122396
{
2413-
InitSymbols();
2414-
2415-
R_ParseContextLast = 0;
2416-
R_ParseContext[0] = '\0';
2397+
LatexTagSymbol = install("latex_tag");
24172398

24182399
parseState.xxInVerbEnv = NULL;
24192400

@@ -2440,6 +2421,9 @@ static SEXP ParseLatex(ParseStatus *status, SEXP srcfile)
24402421

24412422
RELEASE_SV(parseState.Value);
24422423
UNPROTECT(1); /* parseState.mset */
2424+
2425+
if (*status == PARSE_ERROR)
2426+
error("%s", ParseErrorMsg);
24432427

24442428
return parseState.Value;
24452429
}
@@ -2459,14 +2443,6 @@ static int char_getc(void)
24592443
return (c);
24602444
}
24612445

2462-
static
2463-
SEXP R_ParseLatex(SEXP text, ParseStatus *status, SEXP srcfile)
2464-
{
2465-
nextchar_parse = translateCharUTF8(STRING_ELT(text, 0));
2466-
ptr_getc = char_getc;
2467-
return ParseLatex(status, srcfile);
2468-
}
2469-
24702446
/*----------------------------------------------------------------------------
24712447
*
24722448
* The Lexical Analyzer:
@@ -2537,24 +2513,21 @@ static void yyerror(const char *s)
25372513
static char const yyshortunexpected[] = "unexpected %s";
25382514
static char const yylongunexpected[] = "unexpected %s '%s'";
25392515
char *expecting;
2540-
char ParseErrorMsg[PARSE_ERROR_SIZE];
2541-
SEXP filename;
2542-
char ParseErrorFilename[PARSE_ERROR_SIZE];
2543-
2516+
char ErrorTranslation[PARSE_ERROR_SIZE];
25442517
if (!strncmp(s, yyunexpected, sizeof yyunexpected -1)) {
25452518
int i, translated = FALSE;
25462519
/* Edit the error message */
25472520
expecting = strstr(s + sizeof yyunexpected -1, yyexpecting);
25482521
if (expecting) *expecting = '\0';
25492522
for (i = 0; yytname_translations[i]; i += 2) {
25502523
if (!strcmp(s + sizeof yyunexpected - 1, yytname_translations[i])) {
2551-
if (yychar < 256)
2552-
snprintf(ParseErrorMsg, PARSE_ERROR_SIZE,
2524+
if (yychar < 256 || yychar == END_OF_INPUT)
2525+
snprintf(ErrorTranslation, sizeof(ErrorTranslation),
25532526
_(yyshortunexpected),
25542527
i/2 < YYENGLISH ? _(yytname_translations[i+1])
25552528
: yytname_translations[i+1]);
25562529
else
2557-
snprintf(ParseErrorMsg, PARSE_ERROR_SIZE,
2530+
snprintf(ErrorTranslation, sizeof(ErrorTranslation),
25582531
_(yylongunexpected),
25592532
i/2 < YYENGLISH ? _(yytname_translations[i+1])
25602533
: yytname_translations[i+1],
@@ -2564,48 +2537,45 @@ static void yyerror(const char *s)
25642537
}
25652538
}
25662539
if (!translated) {
2567-
if (yychar < 256)
2568-
snprintf(ParseErrorMsg, PARSE_ERROR_SIZE,
2540+
if (yychar < 256 || yychar == END_OF_INPUT)
2541+
snprintf(ErrorTranslation, sizeof(ErrorTranslation),
25692542
_(yyshortunexpected),
25702543
s + sizeof yyunexpected - 1);
25712544
else
2572-
snprintf(ParseErrorMsg, PARSE_ERROR_SIZE,
2545+
snprintf(ErrorTranslation, sizeof(ErrorTranslation),
25732546
_(yylongunexpected),
25742547
s + sizeof yyunexpected - 1, CHAR(STRING_ELT(yylval, 0)));
25752548
}
25762549
if (expecting) {
25772550
translated = FALSE;
25782551
for (i = 0; yytname_translations[i]; i += 2) {
25792552
if (!strcmp(expecting + sizeof yyexpecting - 1, yytname_translations[i])) {
2580-
strcat(ParseErrorMsg, _(yyexpecting));
2581-
strcat(ParseErrorMsg, i/2 < YYENGLISH ? _(yytname_translations[i+1])
2582-
: yytname_translations[i+1]);
2553+
strncat(ErrorTranslation, _(yyexpecting),
2554+
sizeof(ErrorTranslation) - strlen(ErrorTranslation) - 1);
2555+
strncat(ErrorTranslation, i/2 < YYENGLISH
2556+
? _(yytname_translations[i+1])
2557+
: yytname_translations[i+1],
2558+
sizeof(ErrorTranslation) - strlen(ErrorTranslation) - 1);
25832559
translated = TRUE;
25842560
break;
25852561
}
25862562
}
25872563
if (!translated) {
2588-
strcat(ParseErrorMsg, _(yyexpecting));
2589-
strcat(ParseErrorMsg, expecting + sizeof yyexpecting - 1);
2564+
strncat(ErrorTranslation, _(yyexpecting),
2565+
sizeof(ErrorTranslation) - strlen(ErrorTranslation) - 1);
2566+
strncat(ErrorTranslation, expecting + sizeof yyexpecting - 1,
2567+
sizeof(ErrorTranslation) - strlen(ErrorTranslation) - 1);
25902568
}
25912569
}
25922570
} else if (!strncmp(s, yyunknown, sizeof yyunknown-1)) {
2593-
snprintf(ParseErrorMsg, PARSE_ERROR_SIZE,
2571+
snprintf(ErrorTranslation, sizeof(ErrorTranslation),
25942572
"%s '%s'", s, CHAR(STRING_ELT(yylval, 0)));
25952573
} else {
2596-
snprintf(ParseErrorMsg, PARSE_ERROR_SIZE,"%s", s);
2574+
snprintf(ErrorTranslation, sizeof(ErrorTranslation), "%s", s);
25972575
}
2598-
filename = findVar(install("filename"), parseState.SrcFile);
2599-
if (isString(filename) && LENGTH(filename))
2600-
strncpy(ParseErrorFilename, CHAR(STRING_ELT(filename, 0)), PARSE_ERROR_SIZE - 1);
2601-
else
2602-
ParseErrorFilename[0] = '\0';
2603-
if (yylloc.first_line != yylloc.last_line)
2604-
warning("%s:%d-%d: %s",
2605-
ParseErrorFilename, yylloc.first_line, yylloc.last_line, ParseErrorMsg);
2606-
else
2607-
warning("%s:%d: %s",
2608-
ParseErrorFilename, yylloc.first_line, ParseErrorMsg);
2576+
snprintf(ParseErrorMsg, sizeof(ParseErrorMsg),
2577+
"Parse error at %d:%d: %s", yylloc.first_line, yylloc.first_column,
2578+
ErrorTranslation);
26092579
}
26102580

26112581
#define TEXT_PUSH(c) do { \
@@ -2877,7 +2847,7 @@ static void PopState(void) {
28772847
busy = FALSE;
28782848
}
28792849

2880-
/* "do_parseLatex"
2850+
/* "parseLatex"
28812851
28822852
.External2("parseLatex", text, srcfile, verbose, verbatim, verb)
28832853
If there is text then that is read and the other arguments are ignored.
@@ -2894,8 +2864,7 @@ SEXP parseLatex(SEXP call, SEXP op, SEXP args, SEXP env)
28942864
yydebug = 1;
28952865
#endif
28962866

2897-
R_ParseError = 0;
2898-
R_ParseErrorMsg[0] = '\0';
2867+
ParseErrorMsg[0] = '\0';
28992868

29002869
PushState();
29012870

@@ -2908,10 +2877,13 @@ SEXP parseLatex(SEXP call, SEXP op, SEXP args, SEXP env)
29082877
parseState.xxVerbatimList = CAR(args); args = CDR(args);
29092878
parseState.xxVerbList = CAR(args);
29102879

2911-
s = R_ParseLatex(text, &status, source);
2880+
nextchar_parse = translateCharUTF8(STRING_ELT(text, 0));
2881+
ptr_getc = char_getc;
2882+
s = ParseLatex(&status, source);
29122883

29132884
PopState();
29142885

2915-
if (status != PARSE_OK) parseError(call, R_ParseError);
2886+
if (status != PARSE_OK) error("%s", ParseErrorMsg);
2887+
29162888
return s;
29172889
}

0 commit comments

Comments
 (0)