Fix parsing of <= and >= in templated lambda

Skipping between matching delimiters is now done at the token level
rather than the character level.

Partly addresses #2630
This commit is contained in:
Olly Betts 2023-06-07 11:37:45 +12:00
parent 94ba29410c
commit 40033f8498
3 changed files with 94 additions and 194 deletions

View File

@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.2.0 (in progress)
===========================
2023-06-07: olly
#2630 Fix parsing of <= and >= in templated lambda.
Skipping between matching delimiters is now done at the token level
rather than the character level.
2023-06-02: mmomtchev
[Javascript] #2622 Fix support for %typemap(default) and improve
support for default arguments in general.

View File

@ -9,4 +9,8 @@
%inline %{
#include <vector>
auto templated_lambda = []<typename T>(std::vector<T> t){};
// Regression test for parsing bug fixed in SWIG 4.2.0 (#2630)
auto y = []<bool X = 1>=2> { return 1; };
auto z = []<bool X = 1<=2> { return 1; };
%}

View File

@ -1554,126 +1554,55 @@ void Scanner_skip_line(Scanner *s) {
* ----------------------------------------------------------------------------- */
int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) {
char c;
int num_levels = 1;
int state = 0;
String *locator = 0;
Clear(s->text);
Setfile(s->text, Getfile(s->str));
Setline(s->text, s->line);
int old_line = s->line;
long position = Tell(s->str);
Putc((char)startchar, s->text);
while (num_levels > 0) {
if ((c = nextchar(s)) == 0) {
Delete(locator);
return -1;
}
switch (state) {
case 0:
if (c == startchar)
num_levels++;
else if (c == endchar)
num_levels--;
else if (c == '/')
state = 10;
else if (c == '\"')
state = 20;
else if (c == '\'')
state = 30;
int num_levels = 1;
int starttok, endtok;
switch (endchar) {
case '}':
starttok = SWIG_TOKEN_LBRACE;
endtok = SWIG_TOKEN_RBRACE;
break;
case 10:
if (c == '/')
state = 11;
else if (c == '*')
state = 12;
else if (c == startchar) {
state = 0;
num_levels++;
}
else
state = 0;
case ')':
starttok = SWIG_TOKEN_LPAREN;
endtok = SWIG_TOKEN_RPAREN;
break;
case 11:
if (c == '\n')
state = 0;
else
state = 11;
case ']':
starttok = SWIG_TOKEN_LBRACKET;
endtok = SWIG_TOKEN_RBRACKET;
break;
case 12: /* first character inside C comment */
if (c == '*')
state = 14;
else if (c == '@')
state = 40;
else
state = 13;
break;
case 13:
if (c == '*')
state = 14;
break;
case 14: /* possible end of C comment */
if (c == '*')
state = 14;
else if (c == '/')
state = 0;
else
state = 13;
break;
case 20:
if (c == '\"')
state = 0;
else if (c == '\\')
state = 21;
break;
case 21:
state = 20;
break;
case 30:
if (c == '\'')
state = 0;
else if (c == '\\')
state = 31;
break;
case 31:
state = 30;
break;
/* 40-45 SWIG locator checks - a C comment with contents starting: @SWIG */
case 40:
state = (c == 'S') ? 41 : (c == '*') ? 14 : 13;
break;
case 41:
state = (c == 'W') ? 42 : (c == '*') ? 14 : 13;
break;
case 42:
state = (c == 'I') ? 43 : (c == '*') ? 14 : 13;
break;
case 43:
state = (c == 'G') ? 44 : (c == '*') ? 14 : 13;
if (c == 'G') {
Delete(locator);
locator = NewString("/*@SWIG");
}
break;
case 44:
if (c == '*')
state = 45;
Putc(c, locator);
break;
case 45: /* end of SWIG locator in C comment */
if (c == '/') {
state = 0;
Putc(c, locator);
Scanner_locator(s, locator);
} else {
/* malformed locator */
state = (c == '*') ? 14 : 13;
}
case '>':
starttok = SWIG_TOKEN_LESSTHAN;
endtok = SWIG_TOKEN_GREATERTHAN;
break;
default:
break;
assert(0);
}
while (1) {
int tok = Scanner_token(s);
if (tok == starttok) {
num_levels++;
} else if (tok == endtok) {
if (--num_levels == 0) break;
} else if (tok == SWIG_TOKEN_COMMENT) {
char *loc = Char(s->text);
if (strncmp(loc, "/*@SWIG", 7) == 0 && loc[Len(s->text)-3] == '@') {
Scanner_locator(s, s->text);
}
} else if (tok == 0) {
return -1;
}
}
Delete(locator);
Delete(s->text);
s->text = NewStringWithSize(Char(s->str) + position - 1,
Tell(s->str) - position + 1);
Char(s->text)[0] = startchar;
Setfile(s->text, Getfile(s->str));
Setline(s->text, old_line);
return 0;
}
@ -1684,105 +1613,66 @@ int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) {
* ----------------------------------------------------------------------------- */
String *Scanner_get_raw_text_balanced(Scanner *s, int startchar, int endchar) {
String *result = 0;
char c;
String *result = NULL;
int old_line = s->line;
String *old_text = Copy(s->text);
long position = Tell(s->str);
int num_levels = 1;
int state = 0;
Clear(s->text);
Setfile(s->text, Getfile(s->str));
Setline(s->text, s->line);
Putc((char)startchar, s->text);
while (num_levels > 0) {
if ((c = nextchar(s)) == 0) {
Clear(s->text);
Append(s->text, old_text);
Delete(old_text);
s->line = old_line;
return 0;
}
switch (state) {
case 0:
if (c == startchar)
num_levels++;
else if (c == endchar)
num_levels--;
else if (c == '/')
state = 10;
else if (c == '\"')
state = 20;
else if (c == '\'')
state = 30;
int starttok, endtok;
switch (endchar) {
case '}':
starttok = SWIG_TOKEN_LBRACE;
endtok = SWIG_TOKEN_RBRACE;
break;
case 10:
if (c == '/')
state = 11;
else if (c == '*')
state = 12;
else if (c == startchar) {
state = 0;
num_levels++;
}
else
state = 0;
case ')':
starttok = SWIG_TOKEN_LPAREN;
endtok = SWIG_TOKEN_RPAREN;
break;
case 11:
if (c == '\n')
state = 0;
else
state = 11;
case ']':
starttok = SWIG_TOKEN_LBRACKET;
endtok = SWIG_TOKEN_RBRACKET;
break;
case 12: /* first character inside C comment */
if (c == '*')
state = 14;
else
state = 13;
break;
case 13:
if (c == '*')
state = 14;
break;
case 14: /* possible end of C comment */
if (c == '*')
state = 14;
else if (c == '/')
state = 0;
else
state = 13;
break;
case 20:
if (c == '\"')
state = 0;
else if (c == '\\')
state = 21;
break;
case 21:
state = 20;
break;
case 30:
if (c == '\'')
state = 0;
else if (c == '\\')
state = 31;
break;
case 31:
state = 30;
case '>':
starttok = SWIG_TOKEN_LESSTHAN;
endtok = SWIG_TOKEN_GREATERTHAN;
break;
default:
assert(0);
}
while (1) {
int tok = Scanner_token(s);
if (tok == starttok) {
num_levels++;
} else if (tok == endtok) {
if (--num_levels == 0) {
result = NewStringWithSize(Char(s->str) + position - 1,
Tell(s->str) - position + 1);
Char(result)[0] = startchar;
Setfile(result, Getfile(s->str));
Setline(result, old_line);
break;
}
} else if (tok == SWIG_TOKEN_COMMENT) {
char *loc = Char(s->text);
if (strncmp(loc, "/*@SWIG", 7) == 0 && loc[Len(s->text)-3] == '@') {
Scanner_locator(s, s->text);
}
} else if (tok == 0) {
break;
}
}
/* Reset the scanner state. */
Seek(s->str, position, SEEK_SET);
result = Copy(s->text);
Clear(s->text);
Append(s->text, old_text);
Delete(old_text);
Delete(s->text);
s->text = old_text;
s->line = old_line;
return result;
}
/* -----------------------------------------------------------------------------
* Scanner_isoperator()
*