1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <libpspp/message.h>
27 #include <libpspp/assertion.h>
28 #include <language/command.h>
29 #include <libpspp/message.h>
30 #include <data/settings.h>
31 #include <libpspp/getl.h>
32 #include <libpspp/str.h>
33 #include <output/journal.h>
38 #define _(msgid) gettext (msgid)
39 #define N_(msgid) msgid
48 struct string line_buffer;
50 struct source_stream *ss;
52 int token; /* Current token. */
53 double tokval; /* T_POS_NUM, T_NEG_NUM: the token's value. */
55 char tokid [LONG_NAME_LEN + 1]; /* T_ID: the identifier. */
57 struct string tokstr; /* T_ID, T_STRING: token string value.
58 For T_ID, this is not truncated as is
61 char *prog; /* Pointer to next token in line_buffer. */
62 bool dot; /* True only if this line ends with a terminal dot. */
64 int put_token ; /* If nonzero, next token returned by lex_get().
65 Used only in exceptional circumstances. */
67 struct string put_tokstr;
72 static int parse_id (struct lexer *);
74 /* How a string represents its contents. */
77 CHARACTER_STRING, /* Characters. */
78 BINARY_STRING, /* Binary digits. */
79 OCTAL_STRING, /* Octal digits. */
80 HEX_STRING /* Hexadecimal digits. */
83 static int parse_string (struct lexer *, enum string_type);
86 static void dump_token (struct lexer *);
91 /* Initializes the lexer. */
93 lex_create (struct source_stream *ss)
95 struct lexer *lexer = xzalloc (sizeof (*lexer));
97 ds_init_empty (&lexer->tokstr);
98 ds_init_empty (&lexer->put_tokstr);
99 ds_init_empty (&lexer->line_buffer);
105 struct source_stream *
106 lex_get_source_stream (const struct lexer *lex)
112 lex_current_syntax_mode (const struct lexer *lex)
114 return source_stream_current_syntax_mode (lex->ss);
118 lex_current_error_mode (const struct lexer *lex)
120 return source_stream_current_error_mode (lex->ss);
125 lex_destroy (struct lexer *lexer)
129 ds_destroy (&lexer->put_tokstr);
130 ds_destroy (&lexer->tokstr);
131 ds_destroy (&lexer->line_buffer);
138 /* Common functions. */
140 /* Copies put_token, lexer->put_tokstr, put_tokval into token, tokstr,
141 tokval, respectively, and sets tokid appropriately. */
143 restore_token (struct lexer *lexer)
145 assert (lexer->put_token != 0);
146 lexer->token = lexer->put_token;
147 ds_assign_string (&lexer->tokstr, &lexer->put_tokstr);
148 str_copy_trunc (lexer->tokid, sizeof lexer->tokid, ds_cstr (&lexer->tokstr));
149 lexer->tokval = lexer->put_tokval;
150 lexer->put_token = 0;
153 /* Copies token, tokstr, lexer->tokval into lexer->put_token, put_tokstr,
154 put_lexer->tokval respectively. */
156 save_token (struct lexer *lexer)
158 lexer->put_token = lexer->token;
159 ds_assign_string (&lexer->put_tokstr, &lexer->tokstr);
160 lexer->put_tokval = lexer->tokval;
163 /* Parses a single token, setting appropriate global variables to
164 indicate the token's attributes. */
166 lex_get (struct lexer *lexer)
171 if (NULL == lexer->prog && ! lex_get_line (lexer) )
173 lexer->token = T_STOP;
177 /* If a token was pushed ahead, return it. */
178 if (lexer->put_token)
180 restore_token (lexer);
189 /* Skip whitespace. */
190 while (isspace ((unsigned char) *lexer->prog))
205 else if (!lex_get_line (lexer))
208 lexer->token = T_STOP;
215 if (lexer->put_token)
217 restore_token (lexer);
226 /* Actually parse the token. */
227 ds_clear (&lexer->tokstr);
229 switch (*lexer->prog)
232 case '0': case '1': case '2': case '3': case '4':
233 case '5': case '6': case '7': case '8': case '9':
237 /* `-' can introduce a negative number, or it can be a
238 token by itself. If it is not followed by a digit or a
239 decimal point, it is definitely not a number.
240 Otherwise, it might be either, but most of the time we
241 want it as a number. When the syntax calls for a `-'
242 token, lex_negative_to_dash() must be used to break
243 negative numbers into two tokens. */
244 if (*lexer->prog == '-')
246 ds_put_char (&lexer->tokstr, *lexer->prog++);
247 while (isspace ((unsigned char) *lexer->prog))
250 if (!isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.')
255 lexer->token = T_NEG_NUM;
258 lexer->token = T_POS_NUM;
260 /* Parse the number, copying it into tokstr. */
261 while (isdigit ((unsigned char) *lexer->prog))
262 ds_put_char (&lexer->tokstr, *lexer->prog++);
263 if (*lexer->prog == '.')
265 ds_put_char (&lexer->tokstr, *lexer->prog++);
266 while (isdigit ((unsigned char) *lexer->prog))
267 ds_put_char (&lexer->tokstr, *lexer->prog++);
269 if (*lexer->prog == 'e' || *lexer->prog == 'E')
271 ds_put_char (&lexer->tokstr, *lexer->prog++);
272 if (*lexer->prog == '+' || *lexer->prog == '-')
273 ds_put_char (&lexer->tokstr, *lexer->prog++);
274 while (isdigit ((unsigned char) *lexer->prog))
275 ds_put_char (&lexer->tokstr, *lexer->prog++);
278 /* Parse as floating point. */
279 lexer->tokval = strtod (ds_cstr (&lexer->tokstr), &tail);
282 msg (SE, _("%s does not form a valid number."),
283 ds_cstr (&lexer->tokstr));
286 ds_clear (&lexer->tokstr);
287 ds_put_char (&lexer->tokstr, '0');
294 lexer->token = parse_string (lexer, CHARACTER_STRING);
297 case '(': case ')': case ',': case '=': case '+': case '/':
298 lexer->token = *lexer->prog++;
302 if (*++lexer->prog == '*')
305 lexer->token = T_EXP;
312 if (*++lexer->prog == '=')
317 else if (*lexer->prog == '>')
327 if (*++lexer->prog == '=')
337 if (*++lexer->prog == '=')
343 lexer->token = T_NOT;
348 lexer->token = T_AND;
357 if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
358 lexer->token = parse_string (lexer, BINARY_STRING);
360 lexer->token = parse_id (lexer);
364 if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
365 lexer->token = parse_string (lexer, OCTAL_STRING);
367 lexer->token = parse_id (lexer);
371 if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
372 lexer->token = parse_string (lexer, HEX_STRING);
374 lexer->token = parse_id (lexer);
378 if (lex_is_id1 (*lexer->prog))
380 lexer->token = parse_id (lexer);
385 if (isgraph ((unsigned char) *lexer->prog))
386 msg (SE, _("Bad character in input: `%c'."), *lexer->prog++);
388 msg (SE, _("Bad character in input: `\\%o'."), *lexer->prog++);
400 /* Parses an identifier at the current position into tokid and
402 Returns the correct token type. */
404 parse_id (struct lexer *lexer)
406 struct substring rest_of_line
407 = ss_substr (ds_ss (&lexer->line_buffer),
408 ds_pointer_to_position (&lexer->line_buffer, lexer->prog),
410 struct substring id = ss_head (rest_of_line,
411 lex_id_get_length (rest_of_line));
412 lexer->prog += ss_length (id);
414 ds_assign_substring (&lexer->tokstr, id);
415 str_copy_trunc (lexer->tokid, sizeof lexer->tokid, ds_cstr (&lexer->tokstr));
416 return lex_id_to_token (id);
419 /* Reports an error to the effect that subcommand SBC may only be
422 lex_sbc_only_once (const char *sbc)
424 msg (SE, _("Subcommand %s may only be specified once."), sbc);
427 /* Reports an error to the effect that subcommand SBC is
430 lex_sbc_missing (struct lexer *lexer, const char *sbc)
432 lex_error (lexer, _("missing required subcommand %s"), sbc);
435 /* Prints a syntax error message containing the current token and
436 given message MESSAGE (if non-null). */
438 lex_error (struct lexer *lexer, const char *message, ...)
443 token_rep = lex_token_representation (lexer);
444 if (lexer->token == T_STOP)
445 strcpy (where, "end of file");
446 else if (lexer->token == '.')
447 strcpy (where, "end of command");
449 snprintf (where, sizeof where, "`%s'", token_rep);
457 va_start (args, message);
458 vsnprintf (buf, 1024, message, args);
461 msg (SE, _("Syntax error %s at %s."), buf, where);
464 msg (SE, _("Syntax error at %s."), where);
467 /* Checks that we're at end of command.
468 If so, returns a successful command completion code.
469 If not, flags a syntax error and returns an error command
472 lex_end_of_command (struct lexer *lexer)
474 if (lexer->token != '.')
476 lex_error (lexer, _("expecting end of command"));
483 /* Token testing functions. */
485 /* Returns true if the current token is a number. */
487 lex_is_number (struct lexer *lexer)
489 return lexer->token == T_POS_NUM || lexer->token == T_NEG_NUM;
493 /* Returns true if the current token is a string. */
495 lex_is_string (struct lexer *lexer)
497 return lexer->token == T_STRING;
501 /* Returns the value of the current token, which must be a
502 floating point number. */
504 lex_number (struct lexer *lexer)
506 assert (lex_is_number (lexer));
507 return lexer->tokval;
510 /* Returns true iff the current token is an integer. */
512 lex_is_integer (struct lexer *lexer)
514 return (lex_is_number (lexer)
515 && lexer->tokval > LONG_MIN
516 && lexer->tokval <= LONG_MAX
517 && floor (lexer->tokval) == lexer->tokval);
520 /* Returns the value of the current token, which must be an
523 lex_integer (struct lexer *lexer)
525 assert (lex_is_integer (lexer));
526 return lexer->tokval;
529 /* Token matching functions. */
531 /* If TOK is the current token, skips it and returns true
532 Otherwise, returns false. */
534 lex_match (struct lexer *lexer, int t)
536 if (lexer->token == t)
545 /* If the current token is the identifier S, skips it and returns
546 true. The identifier may be abbreviated to its first three
548 Otherwise, returns false. */
550 lex_match_id (struct lexer *lexer, const char *s)
552 if (lexer->token == T_ID
553 && lex_id_match (ss_cstr (s), ss_cstr (lexer->tokid)))
562 /* If the current token is integer N, skips it and returns true.
563 Otherwise, returns false. */
565 lex_match_int (struct lexer *lexer, int x)
567 if (lex_is_integer (lexer) && lex_integer (lexer) == x)
576 /* Forced matches. */
578 /* If this token is identifier S, fetches the next token and returns
580 Otherwise, reports an error and returns zero. */
582 lex_force_match_id (struct lexer *lexer, const char *s)
584 if (lex_match_id (lexer, s))
588 lex_error (lexer, _("expecting `%s'"), s);
593 /* If the current token is T, skips the token. Otherwise, reports an
594 error and returns from the current function with return value false. */
596 lex_force_match (struct lexer *lexer, int t)
598 if (lexer->token == t)
605 lex_error (lexer, _("expecting `%s'"), lex_token_name (t));
610 /* If this token is a string, does nothing and returns true.
611 Otherwise, reports an error and returns false. */
613 lex_force_string (struct lexer *lexer)
615 if (lexer->token == T_STRING)
619 lex_error (lexer, _("expecting string"));
624 /* If this token is an integer, does nothing and returns true.
625 Otherwise, reports an error and returns false. */
627 lex_force_int (struct lexer *lexer)
629 if (lex_is_integer (lexer))
633 lex_error (lexer, _("expecting integer"));
638 /* If this token is a number, does nothing and returns true.
639 Otherwise, reports an error and returns false. */
641 lex_force_num (struct lexer *lexer)
643 if (lex_is_number (lexer))
646 lex_error (lexer, _("expecting number"));
650 /* If this token is an identifier, does nothing and returns true.
651 Otherwise, reports an error and returns false. */
653 lex_force_id (struct lexer *lexer)
655 if (lexer->token == T_ID)
658 lex_error (lexer, _("expecting identifier"));
662 /* Weird token functions. */
664 /* Returns the first character of the next token, except that if the
665 next token is not an identifier, the character returned will not be
666 a character that can begin an identifier. Specifically, the
667 hexstring lead-in X' causes lookahead() to return '. Note that an
668 alphanumeric return value doesn't guarantee an ID token, it could
669 also be a reserved-word token. */
671 lex_look_ahead (struct lexer *lexer)
673 if (lexer->put_token)
674 return lexer->put_token;
678 if (NULL == lexer->prog && ! lex_get_line (lexer) )
683 while (isspace ((unsigned char) *lexer->prog))
690 else if (!lex_get_line (lexer))
693 if (lexer->put_token)
694 return lexer->put_token;
697 if ((toupper ((unsigned char) *lexer->prog) == 'X'
698 || toupper ((unsigned char) *lexer->prog) == 'B'
699 || toupper ((unsigned char) *lexer->prog) == 'O')
700 && (lexer->prog[1] == '\'' || lexer->prog[1] == '"'))
707 /* Makes the current token become the next token to be read; the
708 current token is set to T. */
710 lex_put_back (struct lexer *lexer, int t)
716 /* Makes the current token become the next token to be read; the
717 current token is set to the identifier ID. */
719 lex_put_back_id (struct lexer *lexer, const char *id)
721 assert (lex_id_to_token (ss_cstr (id)) == T_ID);
724 ds_assign_cstr (&lexer->tokstr, id);
725 str_copy_trunc (lexer->tokid, sizeof lexer->tokid, ds_cstr (&lexer->tokstr));
728 /* Weird line processing functions. */
730 /* Returns the entire contents of the current line. */
732 lex_entire_line (const struct lexer *lexer)
734 return ds_cstr (&lexer->line_buffer);
737 const struct string *
738 lex_entire_line_ds (const struct lexer *lexer)
740 return &lexer->line_buffer;
743 /* As lex_entire_line(), but only returns the part of the current line
744 that hasn't already been tokenized. */
746 lex_rest_of_line (const struct lexer *lexer)
751 /* Returns true if the current line ends in a terminal dot,
754 lex_end_dot (const struct lexer *lexer)
759 /* Causes the rest of the current input line to be ignored for
760 tokenization purposes. */
762 lex_discard_line (struct lexer *lexer)
764 ds_cstr (&lexer->line_buffer); /* Ensures ds_end points to something valid */
765 lexer->prog = ds_end (&lexer->line_buffer);
767 lexer->put_token = 0;
771 /* Discards the rest of the current command.
772 When we're reading commands from a file, we skip tokens until
773 a terminal dot or EOF.
774 When we're reading commands interactively from the user,
775 that's just discarding the current line, because presumably
776 the user doesn't want to finish typing a command that will be
779 lex_discard_rest_of_command (struct lexer *lexer)
781 if (!getl_is_interactive (lexer->ss))
783 while (lexer->token != T_STOP && lexer->token != '.')
787 lex_discard_line (lexer);
790 /* Weird line reading functions. */
792 /* Remove C-style comments in STRING, begun by slash-star and
793 terminated by star-slash or newline. */
795 strip_comments (struct string *string)
803 for (cp = ds_cstr (string); *cp; )
805 /* If we're not in a comment, check for quote marks. */
810 else if (*cp == '\'' || *cp == '"')
814 /* If we're not inside a quotation, check for comment. */
817 if (cp[0] == '/' && cp[1] == '*')
824 else if (in_comment && cp[0] == '*' && cp[1] == '/')
833 /* Check commenting. */
840 /* Prepares LINE, which is subject to the given SYNTAX rules, for
841 tokenization by stripping comments and determining whether it
842 is the beginning or end of a command and storing into
843 *LINE_STARTS_COMMAND and *LINE_ENDS_COMMAND appropriately. */
845 lex_preprocess_line (struct string *line,
846 enum syntax_mode syntax,
847 bool *line_starts_command,
848 bool *line_ends_command)
850 strip_comments (line);
851 ds_rtrim (line, ss_cstr (CC_SPACES));
852 *line_ends_command = (ds_chomp (line, get_endcmd ())
853 || (ds_is_empty (line) && get_nulline ()));
854 *line_starts_command = false;
855 if (syntax == GETL_BATCH)
857 int first = ds_first (line);
858 *line_starts_command = !isspace (first);
859 if (first == '+' || first == '-')
860 *ds_data (line) = ' ';
864 /* Reads a line, without performing any preprocessing.
865 Sets *SYNTAX, if SYNTAX is non-null, to the line's syntax
868 lex_get_line_raw (struct lexer *lexer)
870 bool ok = getl_read_line (lexer->ss, &lexer->line_buffer);
871 enum syntax_mode mode = lex_current_syntax_mode (lexer);
872 journal_write (mode == GETL_BATCH, ds_cstr (&lexer->line_buffer));
877 /* Reads a line for use by the tokenizer, and preprocesses it by
878 removing comments, stripping trailing whitespace and the
879 terminal dot, and removing leading indentors. */
881 lex_get_line (struct lexer *lexer)
883 bool line_starts_command;
885 if (!lex_get_line_raw (lexer))
891 lex_preprocess_line (&lexer->line_buffer,
892 lex_current_syntax_mode (lexer),
893 &line_starts_command, &lexer->dot);
895 if (line_starts_command)
896 lexer->put_token = '.';
898 lexer->prog = ds_cstr (&lexer->line_buffer);
904 /* Returns the name of a token. */
906 lex_token_name (int token)
908 if (lex_is_keyword (token))
909 return lex_id_name (token);
910 else if (token < 256)
912 static char t[256][2];
922 /* Returns an ASCII representation of the current token as a
923 malloc()'d string. */
925 lex_token_representation (struct lexer *lexer)
929 switch (lexer->token)
934 return ds_xstrdup (&lexer->tokstr);
942 for (sp = ds_cstr (&lexer->tokstr); sp < ds_end (&lexer->tokstr); sp++)
943 if (!isprint ((unsigned char) *sp))
949 token_rep = xmalloc (2 + ds_length (&lexer->tokstr) * 2 + 1 + 1);
957 for (sp = ds_cstr (&lexer->tokstr); *sp; )
961 *dp++ = (unsigned char) *sp++;
964 for (sp = ds_cstr (&lexer->tokstr); sp < ds_end (&lexer->tokstr); sp++)
966 *dp++ = (((unsigned char) *sp) >> 4)["0123456789ABCDEF"];
967 *dp++ = (((unsigned char) *sp) & 15)["0123456789ABCDEF"];
977 token_rep = xmalloc (1);
982 return xstrdup ("**");
985 return xstrdup (lex_token_name (lexer->token));
991 /* Really weird functions. */
993 /* Most of the time, a `-' is a lead-in to a negative number. But
994 sometimes it's actually part of the syntax. If a dash can be part
995 of syntax then this function is called to rip it off of a
998 lex_negative_to_dash (struct lexer *lexer)
1000 if (lexer->token == T_NEG_NUM)
1002 lexer->token = T_POS_NUM;
1003 lexer->tokval = -lexer->tokval;
1004 ds_assign_substring (&lexer->tokstr, ds_substr (&lexer->tokstr, 1, SIZE_MAX));
1010 /* Skip a COMMENT command. */
1012 lex_skip_comment (struct lexer *lexer)
1016 if (!lex_get_line (lexer))
1018 lexer->put_token = T_STOP;
1023 if (lexer->put_token == '.')
1026 ds_cstr (&lexer->line_buffer); /* Ensures ds_end will point to a valid char */
1027 lexer->prog = ds_end (&lexer->line_buffer);
1033 /* Private functions. */
1035 /* When invoked, tokstr contains a string of binary, octal, or
1036 hex digits, according to TYPE. The string is converted to
1037 characters having the specified values. */
1039 convert_numeric_string_to_char_string (struct lexer *lexer,
1040 enum string_type type)
1042 const char *base_name;
1052 base_name = _("binary");
1057 base_name = _("octal");
1062 base_name = _("hex");
1070 byte_cnt = ds_length (&lexer->tokstr) / chars_per_byte;
1071 if (ds_length (&lexer->tokstr) % chars_per_byte)
1072 msg (SE, _("String of %s digits has %d characters, which is not a "
1074 base_name, (int) ds_length (&lexer->tokstr), chars_per_byte);
1076 p = ds_cstr (&lexer->tokstr);
1077 for (i = 0; i < byte_cnt; i++)
1083 for (j = 0; j < chars_per_byte; j++, p++)
1087 if (*p >= '0' && *p <= '9')
1091 static const char alpha[] = "abcdef";
1092 const char *q = strchr (alpha, tolower ((unsigned char) *p));
1101 msg (SE, _("`%c' is not a valid %s digit."), *p, base_name);
1103 value = value * base + v;
1106 ds_cstr (&lexer->tokstr)[i] = (unsigned char) value;
1109 ds_truncate (&lexer->tokstr, byte_cnt);
1112 /* Parses a string from the input buffer into tokstr. The input
1113 buffer pointer lexer->prog must point to the initial single or double
1114 quote. TYPE indicates the type of string to be parsed.
1115 Returns token type. */
1117 parse_string (struct lexer *lexer, enum string_type type)
1119 if (type != CHARACTER_STRING)
1122 /* Accumulate the entire string, joining sections indicated by +
1126 /* Single or double quote. */
1127 int c = *lexer->prog++;
1129 /* Accumulate section. */
1132 /* Check end of line. */
1133 if (*lexer->prog == '\0')
1135 msg (SE, _("Unterminated string constant."));
1139 /* Double quote characters to embed them in strings. */
1140 if (*lexer->prog == c)
1142 if (lexer->prog[1] == c)
1148 ds_put_char (&lexer->tokstr, *lexer->prog++);
1152 /* Skip whitespace after final quote mark. */
1153 if (lexer->prog == NULL)
1157 while (isspace ((unsigned char) *lexer->prog))
1165 if (!lex_get_line (lexer))
1169 /* Skip plus sign. */
1170 if (*lexer->prog != '+')
1174 /* Skip whitespace after plus sign. */
1175 if (lexer->prog == NULL)
1179 while (isspace ((unsigned char) *lexer->prog))
1187 if (!lex_get_line (lexer))
1189 msg (SE, _("Unexpected end of file in string concatenation."));
1194 /* Ensure that a valid string follows. */
1195 if (*lexer->prog != '\'' && *lexer->prog != '"')
1197 msg (SE, _("String expected following `+'."));
1202 /* We come here when we've finished concatenating all the string sections
1203 into one large string. */
1205 if (type != CHARACTER_STRING)
1206 convert_numeric_string_to_char_string (lexer, type);
1208 if (ds_length (&lexer->tokstr) > 255)
1210 msg (SE, _("String exceeds 255 characters in length (%d characters)."),
1211 (int) ds_length (&lexer->tokstr));
1212 ds_truncate (&lexer->tokstr, 255);
1219 /* Reads one token from the lexer and writes a textual representation
1220 on stdout for debugging purposes. */
1222 dump_token (struct lexer *lexer)
1228 curln = getl_source_location (lexer->ss);
1229 curfn = getl_source_name (lexer->ss);
1231 fprintf (stderr, "%s:%d\t", curfn, curln);
1234 switch (lexer->token)
1237 fprintf (stderr, "ID\t%s\n", lexer->tokid);
1242 fprintf (stderr, "NUM\t%f\n", lexer->tokval);
1246 fprintf (stderr, "STRING\t\"%s\"\n", ds_cstr (&lexer->tokstr));
1250 fprintf (stderr, "STOP\n");
1254 fprintf (stderr, "MISC\tEXP\"");
1258 fprintf (stderr, "MISC\tEOF\n");
1262 if (lex_is_keyword (lexer->token))
1263 fprintf (stderr, "KEYWORD\t%s\n", lex_token_name (lexer->token));
1265 fprintf (stderr, "PUNCT\t%c\n", lexer->token);
1269 #endif /* DUMP_TOKENS */
1272 /* Token Accessor Functions */
1275 lex_token (const struct lexer *lexer)
1277 return lexer->token;
1281 lex_tokval (const struct lexer *lexer)
1283 return lexer->tokval;
1287 lex_tokid (const struct lexer *lexer)
1289 return lexer->tokid;
1292 const struct string *
1293 lex_tokstr (const struct lexer *lexer)
1295 return &lexer->tokstr;