X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flexer.c;h=dd20c8b9524db89a474dc1bad03c2e0eac34223a;hb=97d6c6f6b1922621ca013668eba9a9a9f71d60fe;hp=edcc5a2ae381498d901ae1589c4daf6292715d2f;hpb=3a7fba81ceae5b049d0f7d671e9e3c3c43bbf703;p=pspp diff --git a/src/lexer.c b/src/lexer.c index edcc5a2ae3..dd20c8b952 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -19,7 +19,7 @@ #include #include "lexer.h" -#include +#include "error.h" #include #include #include @@ -34,7 +34,9 @@ #include "settings.h" #include "str.h" -/*#define DUMP_TOKENS 1*/ +/* +#define DUMP_TOKENS 1 +*/ /* Global variables. */ @@ -74,7 +76,9 @@ static int eof; /* If nonzero, next token returned by lex_get(). Used only in exceptional circumstances. */ -static int put; +static int put_token; +static struct string put_tokstr; +static double put_tokval; static void unexpected_eof (void); static inline int check_id (const char *id, size_t len); @@ -91,22 +95,46 @@ static void dump_token (void); void lex_init (void) { + ds_init (NULL, &put_tokstr, 64); if (!lex_get_line ()) unexpected_eof (); } /* Common functions. */ +/* Copies put_token, put_tokstr, put_tokval into token, tokstr, + tokval, respectively, and sets tokid appropriately. */ +static void +restore_token (void) +{ + assert (put_token != 0); + token = put_token; + ds_replace (&tokstr, ds_value (&put_tokstr)); + strncpy (tokid, ds_value (&put_tokstr), 8); + tokid[8] = 0; + tokval = put_tokval; + put_token = 0; +} + +/* Copies token, tokstr, tokval into put_token, put_tokstr, + put_tokval respectively. */ +static void +save_token (void) +{ + put_token = token; + ds_replace (&put_tokstr, ds_value (&tokstr)); + put_tokval = tokval; +} + /* Parses a single token, setting appropriate global variables to indicate the token's attributes. */ void lex_get (void) { /* If a token was pushed ahead, return it. */ - if (put) + if (put_token) { - token = put; - put = 0; + restore_token (); #if DUMP_TOKENS dump_token (); #endif @@ -148,10 +176,9 @@ lex_get (void) return; } - if (put) + if (put_token) { - token = put; - put = 0; + restore_token (); #if DUMP_TOKENS dump_token (); #endif @@ -159,6 +186,7 @@ lex_get (void) } } + /* Actually parse the token. */ cp = prog; ds_clear (&tokstr); @@ -409,6 +437,23 @@ lex_integer (void) assert (lex_integer_p ()); return tokval; } +/* Returns nonzero if the current token is an floating point. */ +int +lex_double_p (void) +{ + return ( token == T_NUM + && tokval != NOT_DOUBLE ); +} + +/* Returns the value of the current token, which must be a + floating point number. */ +double +lex_double (void) +{ + assert (lex_double_p ()); + return tokval; +} + /* Token matching functions. */ @@ -595,8 +640,8 @@ lex_id_match (const char *kw, const char *tok) int lex_look_ahead (void) { - if (put) - return put; + if (put_token) + return put_token; for (;;) { @@ -615,8 +660,8 @@ lex_look_ahead (void) else if (!lex_get_line ()) unexpected_eof (); - if (put) - return put; + if (put_token) + return put_token; } if ((toupper ((unsigned char) *prog) == 'X' @@ -633,45 +678,41 @@ lex_look_ahead (void) void lex_put_back (int t) { - put = token; + save_token (); token = t; } -/* Makes T the next token read. */ +/* Makes the current token become the next token to be read; the + current token is set to the identifier ID. */ void -lex_put_forward (int t) +lex_put_back_id (const char *id) { - put = t; + save_token (); + token = T_ID; + ds_replace (&tokstr, id); + strncpy (tokid, ds_value (&tokstr), 8); + tokid[8] = 0; } /* Weird line processing functions. */ -/* Discards the rest of the current input line for tokenization - purposes, but returns the entire contents of the line for use by - the caller. */ -char * +/* Returns the entire contents of the current line. */ +const char * lex_entire_line (void) { - prog = ds_end (&getl_buf); - dot = 0; return ds_value (&getl_buf); } /* As lex_entire_line(), but only returns the part of the current line that hasn't already been tokenized. - If HAD_DOT is non-null, stores nonzero into *HAD_DOT if the line + If END_DOT is non-null, stores nonzero into *END_DOT if the line ends with a terminal dot, or zero if it doesn't. */ -char * -lex_rest_of_line (int *had_dot) +const char * +lex_rest_of_line (int *end_dot) { - char *s = prog; - prog = ds_end (&getl_buf); - - if (had_dot) - *had_dot = dot; - dot = 0; - - return s; + if (end_dot) + *end_dot = dot; + return prog; } /* Causes the rest of the current input line to be ignored for @@ -679,11 +720,8 @@ lex_rest_of_line (int *had_dot) void lex_discard_line (void) { - msg (SW, _("The rest of this command has been discarded.")); - - ds_clear (&getl_buf); - prog = ds_value (&getl_buf); - dot = put = 0; + prog = ds_end (&getl_buf); + dot = put_token = 0; } /* Sets the current position in the current line to P, which must be @@ -774,12 +812,12 @@ lex_preprocess_line (void) len--; /* Check for and remove terminal dot. */ - if (len > 0 && s[len - 1] == set_endcmd) + if (len > 0 && s[len - 1] == get_endcmd() ) { dot = 1; len--; } - else if (len == 0 && set_nullline) + else if (len == 0 && get_nullline() ) dot = 1; else dot = 0; @@ -797,7 +835,7 @@ lex_preprocess_line (void) if (s[0] == '+' || s[0] == '-' || s[0] == '.') s[0] = ' '; else if (s[0] && !isspace ((unsigned char) s[0])) - lex_put_forward ('.'); + put_token = '.'; } prog = ds_value (&getl_buf); @@ -909,10 +947,11 @@ lex_negative_to_dash (void) { if (token == T_NUM && tokval < 0.0) { - token = '-'; + token = T_NUM; tokval = -tokval; ds_replace (&tokstr, ds_value (&tokstr) + 1); - lex_put_forward (T_NUM); + save_token (); + token = '-'; } } @@ -930,7 +969,7 @@ lex_skip_comment (void) for (;;) { lex_get_line (); - if (put == '.') + if (put_token == '.') break; prog = ds_end (&getl_buf); @@ -1155,40 +1194,40 @@ dump_token (void) getl_location (&curfn, &curln); if (curfn) - printf ("%s:%d\t", curfn, curln); + fprintf (stderr, "%s:%d\t", curfn, curln); } switch (token) { case T_ID: - printf ("ID\t%s\n", tokid); + fprintf (stderr, "ID\t%s\n", tokid); break; case T_NUM: - printf ("NUM\t%f\n", tokval); + fprintf (stderr, "NUM\t%f\n", tokval); break; case T_STRING: - printf ("STRING\t\"%s\"\n", ds_value (&tokstr)); + fprintf (stderr, "STRING\t\"%s\"\n", ds_value (&tokstr)); break; case T_STOP: - printf ("STOP\n"); + fprintf (stderr, "STOP\n"); break; case T_EXP: - puts ("MISC\tEXP"); + fprintf (stderr, "MISC\tEXP\""); break; case 0: - puts ("MISC\tEOF"); + fprintf (stderr, "MISC\tEOF\n"); break; default: if (token >= T_FIRST_KEYWORD && token <= T_LAST_KEYWORD) - printf ("KEYWORD\t%s\n", lex_token_name (token)); + fprintf (stderr, "KEYWORD\t%s\n", lex_token_name (token)); else - printf ("PUNCT\t%c\n", token); + fprintf (stderr, "PUNCT\t%c\n", token); break; } }