Fix tokenizer errors for nested, alternating {} and ()

This commit is contained in:
Mahmoud Al-Qudsi 2018-03-11 20:06:45 -05:00
parent 1629d339de
commit 0620cdf711

View file

@ -109,6 +109,7 @@ ENUM_FLAGS(tok_mode) {
tok_t tokenizer_t::read_string() { tok_t tokenizer_t::read_string() {
tok_mode mode { tok_mode::regular_text }; tok_mode mode { tok_mode::regular_text };
std::vector<int> paran_offsets; std::vector<int> paran_offsets;
std::vector<int> brace_offsets;
std::vector<char> expecting; std::vector<char> expecting;
int slice_offset = 0; int slice_offset = 0;
const wchar_t *const buff_start = this->buff; const wchar_t *const buff_start = this->buff;
@ -146,7 +147,7 @@ tok_t tokenizer_t::read_string() {
mode |= tok_mode::subshell; mode |= tok_mode::subshell;
} }
else if (c == L'{') { else if (c == L'{') {
paran_offsets.push_back(this->buff - this->start); brace_offsets.push_back(this->buff - this->start);
expecting.push_back(L'}'); expecting.push_back(L'}');
mode |= tok_mode::curly_braces; mode |= tok_mode::curly_braces;
} }
@ -162,19 +163,21 @@ tok_t tokenizer_t::read_string() {
default: default:
paran_offsets.pop_back(); paran_offsets.pop_back();
} }
expecting.pop_back();
} }
else if (c == L'}') { else if (c == L'}') {
if (expecting.size() > 0 && expecting.back() == L')') { if (expecting.size() > 0 && expecting.back() == L')') {
return this->call_error(TOK_EXPECTED_PCLOSE_FOUND_BCLOSE, this->start, this->buff); return this->call_error(TOK_EXPECTED_PCLOSE_FOUND_BCLOSE, this->start, this->buff);
} }
switch (paran_offsets.size()) { switch (brace_offsets.size()) {
case 0: case 0:
return this->call_error(TOK_CLOSING_UNOPENED_BRACE, this->start, this->buff); return this->call_error(TOK_CLOSING_UNOPENED_BRACE, this->start, this->buff);
case 1: case 1:
mode &= ~(tok_mode::curly_braces); mode &= ~(tok_mode::curly_braces);
default: default:
paran_offsets.pop_back(); brace_offsets.pop_back();
} }
expecting.pop_back();
} }
else if (c == L'[') { else if (c == L'[') {
if (this->buff != buff_start) { if (this->buff != buff_start) {
@ -247,8 +250,8 @@ tok_t tokenizer_t::read_string() {
this->start + offset_of_open_paran); this->start + offset_of_open_paran);
} }
else if ((mode & tok_mode::curly_braces) == tok_mode::curly_braces) { else if ((mode & tok_mode::curly_braces) == tok_mode::curly_braces) {
assert(paran_offsets.size() > 0); assert(brace_offsets.size() > 0);
size_t offset_of_open_brace = paran_offsets.back(); size_t offset_of_open_brace = brace_offsets.back();
error = this->call_error(TOK_UNTERMINATED_BRACE, buff_start, error = this->call_error(TOK_UNTERMINATED_BRACE, buff_start,
this->start + offset_of_open_brace); this->start + offset_of_open_brace);