X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Flexer%2Flexer.c;h=e72a3e47bc9637d93ad3c1f764b7099686df6d3d;hb=6be12778a162063cbdcd0e79043bd5a4ef2204a6;hp=9a27d867b98cb87e15420671819ab24ccd1ca1fa;hpb=9ade26c8349b4434008c46cf09bc7473ec743972;p=pspp diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 9a27d867b9..e72a3e47bc 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -268,20 +268,116 @@ lex_next_error (struct lexer *lexer, int n0, int n1, const char *format, ...) va_end (args); } -/* Reports an error to the effect that subcommand SBC may only be - specified once. */ +/* Prints a syntax error message saying that OPTION0 or one of the other + strings following it, up to the first NULL, is expected. */ +void +lex_error_expecting (struct lexer *lexer, const char *option0, ...) +{ + enum { MAX_OPTIONS = 8 }; + const char *options[MAX_OPTIONS + 1]; + va_list args; + int n; + + va_start (args, option0); + options[0] = option0; + n = 0; + while (n + 1 < MAX_OPTIONS && options[n] != NULL) + options[++n] = va_arg (args, const char *); + va_end (args); + + switch (n) + { + case 0: + lex_error (lexer, NULL); + break; + + case 1: + lex_error (lexer, _("expecting %s"), options[0]); + break; + + case 2: + lex_error (lexer, _("expecting %s or %s"), options[0], options[1]); + break; + + case 3: + lex_error (lexer, _("expecting %s, %s, or %s"), options[0], options[1], + options[2]); + break; + + case 4: + lex_error (lexer, _("expecting %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3]); + break; + + case 5: + lex_error (lexer, _("expecting %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4]); + break; + + case 6: + lex_error (lexer, _("expecting %s, %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4], + options[5]); + break; + + case 7: + lex_error (lexer, _("expecting %s, %s, %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4], + options[5], options[6]); + break; + + case 8: + lex_error (lexer, _("expecting %s, %s, %s, %s, %s, %s, %s, or %s"), + options[0], options[1], options[2], options[3], options[4], + options[5], options[6], options[7]); + break; + + default: + NOT_REACHED (); + } +} + +/* Reports an error to the effect that subcommand SBC may only be specified + once. + + This function does not take a lexer as an argument or use lex_error(), + because the result would ordinarily just be redundant: "Syntax error at + SUBCOMMAND: Subcommand SUBCOMMAND may only be specified once.", which does + not help the user find the error. */ void lex_sbc_only_once (const char *sbc) { msg (SE, _("Subcommand %s may only be specified once."), sbc); } -/* Reports an error to the effect that subcommand SBC is - missing. */ +/* Reports an error to the effect that subcommand SBC is missing. + + This function does not take a lexer as an argument or use lex_error(), + because a missing subcommand can normally be detected only after the whole + command has been parsed, and so lex_error() would always report "Syntax + error at end of command", which does not help the user find the error. */ void -lex_sbc_missing (struct lexer *lexer, const char *sbc) +lex_sbc_missing (const char *sbc) { - lex_error (lexer, _("missing required subcommand %s"), sbc); + msg (SE, _("Required subcommand %s was not specified."), sbc); +} + +/* Reports an error to the effect that specification SPEC may only be specified + once within subcommand SBC. */ +void +lex_spec_only_once (struct lexer *lexer, const char *sbc, const char *spec) +{ + lex_error (lexer, _("%s may only be specified once within subcommand %s"), + spec, sbc); +} + +/* Reports an error to the effect that specification SPEC is missing within + subcommand SBC. */ +void +lex_spec_missing (struct lexer *lexer, const char *sbc, const char *spec) +{ + lex_error (lexer, _("Required %s specification missing from %s subcommand"), + sbc, spec); } /* Prints a syntax error message containing the current token and @@ -491,7 +587,7 @@ lex_force_match_id (struct lexer *lexer, const char *identifier) return true; else { - lex_error (lexer, _("expecting `%s'"), identifier); + lex_error_expecting (lexer, identifier, NULL_SENTINEL); return false; } } @@ -508,7 +604,9 @@ lex_force_match (struct lexer *lexer, enum token_type type) } else { - lex_error (lexer, _("expecting `%s'"), token_type_to_string (type)); + char *s = xasprintf ("`%s'", token_type_to_string (type)); + lex_error_expecting (lexer, s, NULL_SENTINEL); + free (s); return false; } } @@ -527,6 +625,21 @@ lex_force_string (struct lexer *lexer) } } +/* If the current token is a string or an identifier, does nothing and returns + true. Otherwise, reports an error and returns false. + + This is meant for use in syntactic situations where we want to encourage the + user to supply a quoted string, but for compatibility we also accept + identifiers. (One example of such a situation is file names.) Therefore, + the error message issued when the current token is wrong only says that a + string is expected and doesn't mention that an identifier would also be + accepted. */ +bool +lex_force_string_or_id (struct lexer *lexer) +{ + return lex_is_integer (lexer) || lex_force_string (lexer); +} + /* If the current token is an integer, does nothing and returns true. Otherwise, reports an error and returns false. */ bool @@ -1324,6 +1437,7 @@ lex_source_get__ (const struct lex_source *src_) const char *newline; const char *line; size_t line_len; + char *syntax; line = &src->buffer[src->journal_pos - src->tail]; newline = rawmemchr (line, '\n'); @@ -1331,8 +1445,12 @@ lex_source_get__ (const struct lex_source *src_) if (line_len > 0 && line[line_len - 1] == '\r') line_len--; - text_item_submit (text_item_create_nocopy (TEXT_ITEM_SYNTAX, - xmemdup0 (line, line_len))); + syntax = malloc (line_len + 2); + memcpy (syntax, line, line_len); + syntax[line_len] = '\n'; + syntax[line_len + 1] = '\0'; + + text_item_submit (text_item_create_nocopy (TEXT_ITEM_SYNTAX, syntax)); src->journal_pos += newline - line + 1; } @@ -1447,8 +1565,8 @@ static void lex_source_destroy (struct lex_source *src) { char *file_name = src->reader->file_name; - if (src->reader->class->close != NULL) - src->reader->class->close (src->reader); + if (src->reader->class->destroy != NULL) + src->reader->class->destroy (src->reader); free (file_name); free (src->buffer); while (!deque_is_empty (&src->deque))