• R/O
  • SSH
  • HTTPS

yash: Commit


Commit MetaInfo

Revision3878 (tree)
Time2018-09-19 00:55:21
Authormagicant

Log Message

Restructure parser token error printing

The check_closing_token function is changed to the is_closing_tokentype
function. The get_errmsg_unexpected_token function is changed to the
get_errmsg_unexpected_tokentype function. The
print_errmsg_token_unexpected function is added.

The tryparse_redirect function is modified to keep the redundant error
message suppressed.

Change Summary

Incremental Difference

--- yash/branches/token_based_parser/parser.c (revision 3877)
+++ yash/branches/token_based_parser/parser.c (revision 3878)
@@ -284,6 +284,8 @@
284284 __attribute__((pure));
285285 static bool is_command_delimiter_tokentype(tokentype_T tt)
286286 __attribute__((const));
287+static bool is_closing_tokentype(tokentype_T tt)
288+ __attribute__((const));
287289
288290
289291 /* Checks if the specified character can be used in a portable variable name.
@@ -486,7 +488,28 @@
486488 }
487489 }
488490
491+/* Determines if the specified token is a 'closing' token such as ")", "}", and
492+ * "fi". Closing tokens delimit and/or lists. */
493+bool is_closing_tokentype(tokentype_T tt)
494+{
495+ switch (tt) {
496+ case TT_RPAREN:
497+ case TT_RBRACE:
498+ case TT_THEN:
499+ case TT_ELIF:
500+ case TT_ELSE:
501+ case TT_FI:
502+ case TT_DO:
503+ case TT_DONE:
504+ case TT_DOUBLE_SEMICOLON:
505+ case TT_ESAC:
506+ return true;
507+ default:
508+ return false;
509+ }
510+}
489511
512+
490513 /********** Parser **********/
491514
492515 /* Holds data that are used in parsing. */
@@ -552,8 +575,6 @@
552575 __attribute__((pure,nonnull));
553576 static const wchar_t *check_opening_token(parsestate_T *ps)
554577 __attribute__((nonnull));
555-static const wchar_t *check_closing_token(parsestate_T *ps)
556- __attribute__((nonnull));
557578 static bool psubstitute_alias(parsestate_T *ps, substaliasflags_T f)
558579 __attribute__((nonnull));
559580 static void psubstitute_alias_recursive(parsestate_T *ps, substaliasflags_T f)
@@ -645,7 +666,9 @@
645666 parsestate_T *ps, bool backquote, bool stoponnewline,
646667 wordunit_T **lastp)
647668 __attribute__((nonnull));
648-static const char *get_errmsg_unexpected_token(const wchar_t *t)
669+static const char *get_errmsg_unexpected_tokentype(tokentype_T tokentype)
670+ __attribute__((const));
671+static void print_errmsg_token_unexpected(parsestate_T *ps)
649672 __attribute__((nonnull));
650673 static void print_errmsg_token_missing(parsestate_T *ps, const wchar_t *t)
651674 __attribute__((nonnull));
@@ -1158,30 +1181,6 @@
11581181 return NULL;
11591182 }
11601183
1161-/* Checks if there is a 'closing' token such as ")", "}", and "fi" at the
1162- * current position. If there is one, the token string is returned.
1163- * Otherwise, NULL is returned.
1164- * This function calls `ensure_buffer(ps, 5)'. */
1165-/* Closing tokens delimit and/or lists. */
1166-const wchar_t *check_closing_token(parsestate_T *ps)
1167-{
1168- ensure_buffer(ps, 5);
1169- if (ps->src.contents[ps->index] == L')')
1170- return L")";
1171- if (ps->src.contents[ps->index] == L';' &&
1172- ps->src.contents[ps->index + 1] == L';')
1173- return L";;";
1174- if (has_token(ps, L"}")) return L"}";
1175- if (has_token(ps, L"then")) return L"then";
1176- if (has_token(ps, L"else")) return L"else";
1177- if (has_token(ps, L"elif")) return L"elif";
1178- if (has_token(ps, L"fi")) return L"fi";
1179- if (has_token(ps, L"do")) return L"do";
1180- if (has_token(ps, L"done")) return L"done";
1181- if (has_token(ps, L"esac")) return L"esac";
1182- return NULL;
1183-}
1184-
11851184 /* Performs alias substitution with the given parse state. Proceeds to the
11861185 * next token if substitution occurred. */
11871186 bool psubstitute_alias(parsestate_T *ps, substaliasflags_T flags)
@@ -1242,7 +1241,7 @@
12421241 if (ps->tokentype == TT_END_OF_INPUT) {
12431242 break;
12441243 } else if (ps->tokentype == TT_RPAREN) {
1245- serror(ps, get_errmsg_unexpected_token(L")"), L")");
1244+ print_errmsg_token_unexpected(ps);
12461245 break;
12471246 } else if (need_separator) {
12481247 serror(ps, Ngt("`;' or `&' is missing"));
@@ -1252,7 +1251,7 @@
12521251 if (parse_newline_list(ps))
12531252 need_separator = false;
12541253 if (need_separator || ps->tokentype == TT_END_OF_INPUT ||
1255- check_closing_token(ps))
1254+ is_closing_tokentype(ps->tokentype))
12561255 break;
12571256 }
12581257
@@ -1416,26 +1415,10 @@
14161415 {
14171416 ps->reparse = false;
14181417
1419- /* Note: `check_closing_token' calls `ensure_buffer(ps, 5)'. */
1420- const wchar_t *t = check_closing_token(ps);
1421- if (t != NULL) {
1422- serror(ps, get_errmsg_unexpected_token(t), t);
1418+ if (ps->tokentype == TT_BANG || ps->tokentype == TT_IN ||
1419+ is_closing_tokentype(ps->tokentype)) {
1420+ print_errmsg_token_unexpected(ps);
14231421 return NULL;
1424- } else if (ps->tokentype == TT_BANG) {
1425- serror(ps, get_errmsg_unexpected_token(L"!"), L"!");
1426- return NULL;
1427- } else if (ps->tokentype == TT_IN) {
1428- serror(ps, get_errmsg_unexpected_token(L"in"), L"in");
1429- return NULL;
1430- } else if (ps->tokentype == TT_LPAREN) {
1431- return parse_compound_command(ps);
1432- } else if (is_command_delimiter_tokentype(ps->tokentype)) {
1433- if (ps->tokentype == TT_END_OF_INPUT || ps->tokentype == TT_NEWLINE)
1434- serror(ps, Ngt("a command is missing at the end of input"));
1435- else
1436- serror(ps, Ngt("a command is missing before `%lc'"),
1437- (wint_t) ps->src.contents[ps->index]);
1438- return NULL;
14391422 }
14401423
14411424 command_T *result = parse_compound_command(ps);
@@ -1456,6 +1439,18 @@
14561439 redir_T **redirlastp = parse_assignments_and_redirects(ps, result);
14571440 result->c_words = parse_words_and_redirects(ps, redirlastp, true);
14581441
1442+ if (result->c_words[0] == NULL && result->c_assigns == NULL &&
1443+ result->c_redirs == NULL) {
1444+ /* an empty command */
1445+ comsfree(result);
1446+ if (ps->tokentype == TT_END_OF_INPUT || ps->tokentype == TT_NEWLINE)
1447+ serror(ps, Ngt("a command is missing at the end of input"));
1448+ else
1449+ serror(ps, Ngt("a command is missing before `%lc'"),
1450+ (wint_t) ps->src.contents[ps->index]);
1451+ return NULL;
1452+ }
1453+
14591454 return try_reparse_as_function(ps, result);
14601455 }
14611456
@@ -1707,16 +1702,15 @@
17071702 parse_here_document_tag:
17081703 next_token(ps);
17091704 psubstitute_alias_recursive(ps, 0);
1705+ result->rd_hereend =
1706+ xwcsndup(&ps->src.contents[ps->index], ps->next_index - ps->index);
1707+ result->rd_herecontent = NULL;
17101708 if (ps->token == NULL) {
17111709 serror(ps, Ngt("the end-of-here-document indicator is missing"));
1712- free(result);
1713- return NULL;
1710+ } else {
1711+ pl_add(&ps->pending_heredocs, result);
1712+ next_token(ps);
17141713 }
1715- result->rd_hereend =
1716- xwcsndup(&ps->src.contents[ps->index], ps->next_index - ps->index);
1717- result->rd_herecontent = NULL;
1718- pl_add(&ps->pending_heredocs, result);
1719- next_token(ps);
17201714 return result;
17211715
17221716 parse_command:
@@ -3031,60 +3025,56 @@
30313025
30323026 /***** Auxiliaries about Error Messages *****/
30333027
3034-const char *get_errmsg_unexpected_token(const wchar_t *t)
3028+const char *get_errmsg_unexpected_tokentype(tokentype_T tokentype)
30353029 {
3036- switch (t[0]) {
3037- case L')':
3038- assert(wcscmp(t, L")") == 0);
3030+ switch (tokentype) {
3031+ case TT_RPAREN:
30393032 return Ngt("encountered `%ls' without a matching `('");
3040- case L'}':
3041- assert(wcscmp(t, L"}") == 0);
3033+ case TT_RBRACE:
30423034 return Ngt("encountered `%ls' without a matching `{'");
3043- case L';':
3044- assert(wcscmp(t, L";;") == 0);
3035+ case TT_DOUBLE_SEMICOLON:
30453036 return Ngt("`%ls' is used outside `case'");
3046- case L'!':
3047- assert(wcscmp(t, L"!") == 0);
3037+ case TT_BANG:
30483038 return Ngt("`%ls' cannot be used as a command name");
3049- case L'i':
3050- assert(wcscmp(t, L"in") == 0);
3039+ case TT_IN:
30513040 return Ngt("`%ls' cannot be used as a command name");
3052- case L'f':
3053- assert(wcscmp(t, L"fi") == 0);
3041+ case TT_FI:
30543042 return Ngt("encountered `%ls' "
30553043 "without a matching `if' and/or `then'");
3056- case L't':
3057- assert(wcscmp(t, L"then") == 0);
3044+ case TT_THEN:
30583045 return Ngt("encountered `%ls' without a matching `if' or `elif'");
3059- case L'd':
3060- assert(t[1] == L'o');
3061- if (t[2] == L'\0') {
3062- assert(wcscmp(t, L"do") == 0);
3063- return Ngt("encountered `%ls' "
3064- "without a matching `for', `while', or `until'");
3065- } else {
3066- assert(wcscmp(t, L"done") == 0);
3067- return Ngt("encountered `%ls' without a matching `do'");
3068- }
3069- case L'e':
3070- if (t[1] == L's') {
3071- assert(wcscmp(t, L"esac") == 0);
3072- return Ngt("encountered `%ls' without a matching `case'");
3073- } else {
3074- assert(wcscmp(t, L"else") == 0 || wcscmp(t, L"elif") == 0);
3075- return Ngt("encountered `%ls' "
3046+ case TT_DO:
3047+ return Ngt("encountered `%ls' "
3048+ "without a matching `for', `while', or `until'");
3049+ case TT_DONE:
3050+ return Ngt("encountered `%ls' without a matching `do'");
3051+ case TT_ESAC:
3052+ return Ngt("encountered `%ls' without a matching `case'");
3053+ case TT_ELIF:
3054+ case TT_ELSE:
3055+ return Ngt("encountered `%ls' "
30763056 "without a matching `if' and/or `then'");
3077- }
30783057 default:
30793058 assert(false);
30803059 }
30813060 }
30823061
3062+void print_errmsg_token_unexpected(parsestate_T *ps)
3063+{
3064+ assert(ps->index <= ps->next_index);
3065+ size_t length = ps->next_index - ps->index;
3066+ wchar_t token[length + 1];
3067+ wcsncpy(token, &ps->src.contents[ps->index], length);
3068+ token[length] = L'\0';
3069+
3070+ const char *message = get_errmsg_unexpected_tokentype(ps->tokentype);
3071+ serror(ps, message, token);
3072+}
3073+
30833074 void print_errmsg_token_missing(parsestate_T *ps, const wchar_t *t)
30843075 {
3085- const wchar_t *atoken = check_closing_token(ps);
3086- if (atoken != NULL) {
3087- serror(ps, get_errmsg_unexpected_token(atoken), atoken);
3076+ if (is_closing_tokentype(ps->tokentype)) {
3077+ print_errmsg_token_unexpected(ps);
30883078 serror(ps, Ngt("(maybe you missed `%ls'?)"), t);
30893079 } else {
30903080 serror(ps, Ngt("`%ls' is missing"), t);
Show on old repository browser