X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Flexer%2Flexer.c;h=9b879c71ec5d57484bb4105a0540e6db2b6b11d9;hb=173d1687aea88e0e5e1b1d8615ed68ebefb15d08;hp=71597302032a48cbf31f4d12d028f54bbc009780;hpb=68f08c4bb53fcde16035b622bdb6e9529f9cf3ae;p=pspp diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 7159730203..9b879c71ec 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,23 +17,24 @@ #include #include "lexer.h" #include -#include +#include +#include #include #include #include #include +#include #include -#include #include #include #include -#include #include #include #include #include +#include -#include "size_max.h" +#include "xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -53,7 +54,7 @@ struct lexer int token; /* Current token. */ double tokval; /* T_POS_NUM, T_NEG_NUM: the token's value. */ - char tokid [LONG_NAME_LEN + 1]; /* T_ID: the identifier. */ + char tokid [VAR_NAME_LEN + 1]; /* T_ID: the identifier. */ struct string tokstr; /* T_ID, T_STRING: token string value. For T_ID, this is not truncated as is @@ -175,20 +176,20 @@ lex_get (struct lexer *lexer) return; } - /* If a token was pushed ahead, return it. */ - if (lexer->put_token) - { - restore_token (lexer); + /* If a token was pushed ahead, return it. */ + if (lexer->put_token) + { + restore_token (lexer); #if DUMP_TOKENS dump_token (lexer); #endif - return; - } + return; + } - for (;;) - { - /* Skip whitespace. */ - while (isspace ((unsigned char) *lexer->prog)) + for (;;) + { + /* Skip whitespace. */ + while (c_isspace ((unsigned char) *lexer->prog)) lexer->prog++; if (*lexer->prog) @@ -245,10 +246,10 @@ lex_get (struct lexer *lexer) if (*lexer->prog == '-') { ds_put_char (&lexer->tokstr, *lexer->prog++); - while (isspace ((unsigned char) *lexer->prog)) + while (c_isspace ((unsigned char) *lexer->prog)) lexer->prog++; - if (!isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.') + if (!c_isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.') { lexer->token = '-'; break; @@ -259,12 +260,12 @@ lex_get (struct lexer *lexer) lexer->token = T_POS_NUM; /* Parse the number, copying it into tokstr. */ - while (isdigit ((unsigned char) *lexer->prog)) + while (c_isdigit ((unsigned char) *lexer->prog)) ds_put_char (&lexer->tokstr, *lexer->prog++); if (*lexer->prog == '.') { ds_put_char (&lexer->tokstr, *lexer->prog++); - while (isdigit ((unsigned char) *lexer->prog)) + while (c_isdigit ((unsigned char) *lexer->prog)) ds_put_char (&lexer->tokstr, *lexer->prog++); } if (*lexer->prog == 'e' || *lexer->prog == 'E') @@ -272,12 +273,12 @@ lex_get (struct lexer *lexer) ds_put_char (&lexer->tokstr, *lexer->prog++); if (*lexer->prog == '+' || *lexer->prog == '-') ds_put_char (&lexer->tokstr, *lexer->prog++); - while (isdigit ((unsigned char) *lexer->prog)) + while (c_isdigit ((unsigned char) *lexer->prog)) ds_put_char (&lexer->tokstr, *lexer->prog++); } /* Parse as floating point. */ - lexer->tokval = strtod (ds_cstr (&lexer->tokstr), &tail); + lexer->tokval = c_strtod (ds_cstr (&lexer->tokstr), &tail); if (*tail) { msg (SE, _("%s does not form a valid number."), @@ -296,6 +297,7 @@ lex_get (struct lexer *lexer) break; case '(': case ')': case ',': case '=': case '+': case '/': + case '[': case ']': lexer->token = *lexer->prog++; break; @@ -383,10 +385,10 @@ lex_get (struct lexer *lexer) } else { - if (isgraph ((unsigned char) *lexer->prog)) - msg (SE, _("Bad character in input: `%c'."), *lexer->prog++); - else - msg (SE, _("Bad character in input: `\\%o'."), *lexer->prog++); + unsigned char c = *lexer->prog++; + char *c_name = xasprintf (c_isgraph (c) ? "%c" : "\\%o", c); + msg (SE, _("Bad character in input: `%s'."), c_name); + free (c_name); continue; } } @@ -513,8 +515,7 @@ bool lex_is_integer (struct lexer *lexer) { return (lex_is_number (lexer) - && lexer->tokval != NOT_LONG - && lexer->tokval >= LONG_MIN + && lexer->tokval > LONG_MIN && lexer->tokval <= LONG_MAX && floor (lexer->tokval) == lexer->tokval); } @@ -550,9 +551,19 @@ lex_match (struct lexer *lexer, int t) Otherwise, returns false. */ bool lex_match_id (struct lexer *lexer, const char *s) +{ + return lex_match_id_n (lexer, s, 3); +} + +/* If the current token is the identifier S, skips it and returns + true. The identifier may be abbreviated to its first N + letters. + Otherwise, returns false. */ +bool +lex_match_id_n (struct lexer *lexer, const char *s, size_t n) { if (lexer->token == T_ID - && lex_id_match (ss_cstr (s), ss_cstr (lexer->tokid))) + && lex_id_match_n (ss_cstr (s), ss_cstr (lexer->tokid), n)) { lex_get (lexer); return true; @@ -682,7 +693,7 @@ lex_look_ahead (struct lexer *lexer) for (;;) { - while (isspace ((unsigned char) *lexer->prog)) + while (c_isspace ((unsigned char) *lexer->prog)) lexer->prog++; if (*lexer->prog) break; @@ -851,28 +862,28 @@ lex_preprocess_line (struct string *line, { strip_comments (line); ds_rtrim (line, ss_cstr (CC_SPACES)); - *line_ends_command = (ds_chomp (line, get_endcmd ()) - || (ds_is_empty (line) && get_nulline ())); + *line_ends_command = (ds_chomp (line, settings_get_endcmd ()) + || (ds_is_empty (line) && settings_get_nulline ())); *line_starts_command = false; if (syntax == GETL_BATCH) { int first = ds_first (line); - *line_starts_command = !isspace (first); + *line_starts_command = !c_isspace (first); if (first == '+' || first == '-') *ds_data (line) = ' '; } } -/* Reads a line, without performing any preprocessing. - Sets *SYNTAX, if SYNTAX is non-null, to the line's syntax - mode. */ +/* Reads a line, without performing any preprocessing. */ bool lex_get_line_raw (struct lexer *lexer) { bool ok = getl_read_line (lexer->ss, &lexer->line_buffer); - enum syntax_mode mode = lex_current_syntax_mode (lexer); - journal_write (mode == GETL_BATCH, ds_cstr (&lexer->line_buffer)); - + if (ok) + { + const char *line = ds_cstr (&lexer->line_buffer); + text_item_submit (text_item_create (TEXT_ITEM_SYNTAX, line)); + } return ok; } @@ -942,7 +953,7 @@ lex_token_representation (struct lexer *lexer) char *sp, *dp; for (sp = ds_cstr (&lexer->tokstr); sp < ds_end (&lexer->tokstr); sp++) - if (!isprint ((unsigned char) *sp)) + if (!c_isprint ((unsigned char) *sp)) { hexstring = 1; break; @@ -1071,9 +1082,9 @@ convert_numeric_string_to_char_string (struct lexer *lexer, byte_cnt = ds_length (&lexer->tokstr) / chars_per_byte; if (ds_length (&lexer->tokstr) % chars_per_byte) - msg (SE, _("String of %s digits has %d characters, which is not a " + msg (SE, _("String of %s digits has %zu characters, which is not a " "multiple of %d."), - base_name, (int) ds_length (&lexer->tokstr), chars_per_byte); + base_name, ds_length (&lexer->tokstr), chars_per_byte); p = ds_cstr (&lexer->tokstr); for (i = 0; i < byte_cnt; i++) @@ -1156,7 +1167,7 @@ parse_string (struct lexer *lexer, enum string_type type) break; for (;;) { - while (isspace ((unsigned char) *lexer->prog)) + while (c_isspace ((unsigned char) *lexer->prog)) lexer->prog++; if (*lexer->prog) break; @@ -1178,7 +1189,7 @@ parse_string (struct lexer *lexer, enum string_type type) break; for (;;) { - while (isspace ((unsigned char) *lexer->prog)) + while (c_isspace ((unsigned char) *lexer->prog)) lexer->prog++; if (*lexer->prog) break; @@ -1207,13 +1218,6 @@ finish: if (type != CHARACTER_STRING) convert_numeric_string_to_char_string (lexer, type); - if (ds_length (&lexer->tokstr) > 255) - { - msg (SE, _("String exceeds 255 characters in length (%d characters)."), - (int) ds_length (&lexer->tokstr)); - ds_truncate (&lexer->tokstr, 255); - } - return T_STRING; } @@ -1245,7 +1249,7 @@ dump_token (struct lexer *lexer) break; case T_STRING: - fprintf (stderr, "STRING\t\"%s\"\n", ds_cstr (&lexer->tokstr)); + fprintf (stderr, "STRING\t`%s'\n", ds_cstr (&lexer->tokstr)); break; case T_STOP: @@ -1296,3 +1300,28 @@ lex_tokstr (const struct lexer *lexer) { return &lexer->tokstr; } + +/* If the lexer is positioned at the (pseudo)identifier S, which + may contain a hyphen ('-'), skips it and returns true. Each + half of the identifier may be abbreviated to its first three + letters. + Otherwise, returns false. */ +bool +lex_match_hyphenated_word (struct lexer *lexer, const char *s) +{ + const char *hyphen = strchr (s, '-'); + if (hyphen == NULL) + return lex_match_id (lexer, s); + else if (lexer->token != T_ID + || !lex_id_match (ss_buffer (s, hyphen - s), ss_cstr (lexer->tokid)) + || lex_look_ahead (lexer) != '-') + return false; + else + { + lex_get (lexer); + lex_force_match (lexer, '-'); + lex_force_match_id (lexer, hyphen + 1); + return true; + } +} +