X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Flexer%2Flexer.c;h=cc8cab808948973b08e9145f337edf8028afb70b;hb=6f48190d3435800eec4984e927757242dafaef45;hp=4e10ec22478caf8c8e3579d9e8b8094b0b31f688;hpb=fdcc4b6875ccdbf7bd01bc401e87afbeb71c2bfd;p=pspp-builds.git diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index 4e10ec22..cc8cab80 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -22,18 +22,17 @@ #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) @@ -43,6 +42,7 @@ #define DUMP_TOKENS 0 + struct lexer { struct string line_buffer; @@ -52,7 +52,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 @@ -108,6 +108,18 @@ lex_get_source_stream (const struct lexer *lex) return lex->ss; } +enum syntax_mode +lex_current_syntax_mode (const struct lexer *lex) +{ + return source_stream_current_syntax_mode (lex->ss); +} + +enum error_mode +lex_current_error_mode (const struct lexer *lex) +{ + return source_stream_current_error_mode (lex->ss); +} + void lex_destroy (struct lexer *lexer) @@ -283,6 +295,7 @@ lex_get (struct lexer *lexer) break; case '(': case ')': case ',': case '=': case '+': case '/': + case '[': case ']': lexer->token = *lexer->prog++; break; @@ -500,8 +513,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); } @@ -537,9 +549,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; @@ -832,14 +854,14 @@ strip_comments (struct string *string) *LINE_STARTS_COMMAND and *LINE_ENDS_COMMAND appropriately. */ void lex_preprocess_line (struct string *line, - enum getl_syntax syntax, + enum syntax_mode syntax, bool *line_starts_command, bool *line_ends_command) { 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) { @@ -854,15 +876,11 @@ lex_preprocess_line (struct string *line, Sets *SYNTAX, if SYNTAX is non-null, to the line's syntax mode. */ bool -lex_get_line_raw (struct lexer *lexer, enum getl_syntax *syntax) +lex_get_line_raw (struct lexer *lexer) { - enum getl_syntax dummy; - bool ok; - - if (syntax == NULL) - syntax = &dummy; - ok = getl_read_line (lexer->ss, &lexer->line_buffer, syntax); - journal_write (*syntax == GETL_BATCH, ds_cstr (&lexer->line_buffer)); + 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)); return ok; } @@ -874,15 +892,15 @@ bool lex_get_line (struct lexer *lexer) { bool line_starts_command; - enum getl_syntax syntax = GETL_BATCH; - if (!lex_get_line_raw (lexer, &syntax)) + if (!lex_get_line_raw (lexer)) { lexer->prog = NULL; return false; } - lex_preprocess_line (&lexer->line_buffer, syntax, + lex_preprocess_line (&lexer->line_buffer, + lex_current_syntax_mode (lexer), &line_starts_command, &lexer->dot); if (line_starts_command) @@ -1062,9 +1080,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++) @@ -1200,8 +1218,8 @@ finish: if (ds_length (&lexer->tokstr) > 255) { - msg (SE, _("String exceeds 255 characters in length (%d characters)."), - (int) ds_length (&lexer->tokstr)); + msg (SE, _("String exceeds 255 characters in length (%zu characters)."), + ds_length (&lexer->tokstr)); ds_truncate (&lexer->tokstr, 255); } @@ -1287,3 +1305,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; + } +} +