1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2009 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>
28 #include <libpspp/assertion.h>
29 #include <language/command.h>
30 #include <libpspp/message.h>
31 #include <data/settings.h>
32 #include <libpspp/getl.h>
33 #include <libpspp/str.h>
34 #include <output/journal.h>
35 #include <output/text-item.h>
40 #define _(msgid) gettext (msgid)
41 #define N_(msgid) msgid
50 struct string line_buffer;
52 struct source_stream *ss;
54 int token; /* Current token. */
55 double tokval; /* T_POS_NUM, T_NEG_NUM: the token's value. */
57 char tokid [VAR_NAME_LEN + 1]; /* T_ID: the identifier. */
59 struct string tokstr; /* T_ID, T_STRING: token string value.
60 For T_ID, this is not truncated as is
63 char *prog; /* Pointer to next token in line_buffer. */
64 bool dot; /* True only if this line ends with a terminal dot. */
66 int put_token ; /* If nonzero, next token returned by lex_get().
67 Used only in exceptional circumstances. */
69 struct string put_tokstr;
74 static int parse_id (struct lexer *);
76 /* How a string represents its contents. */
79 CHARACTER_STRING, /* Characters. */
80 BINARY_STRING, /* Binary digits. */
81 OCTAL_STRING, /* Octal digits. */
82 HEX_STRING /* Hexadecimal digits. */
85 static int parse_string (struct lexer *, enum string_type);
88 static void dump_token (struct lexer *);
93 /* Initializes the lexer. */
95 lex_create (struct source_stream *ss)
97 struct lexer *lexer = xzalloc (sizeof (*lexer));
99 ds_init_empty (&lexer->tokstr);
100 ds_init_empty (&lexer->put_tokstr);
101 ds_init_empty (&lexer->line_buffer);
107 struct source_stream *
108 lex_get_source_stream (const struct lexer *lex)
114 lex_current_syntax_mode (const struct lexer *lex)
116 return source_stream_current_syntax_mode (lex->ss);
120 lex_current_error_mode (const struct lexer *lex)
122 return source_stream_current_error_mode (lex->ss);
127 lex_destroy (struct lexer *lexer)
131 ds_destroy (&lexer->put_tokstr);
132 ds_destroy (&lexer->tokstr);
133 ds_destroy (&lexer->line_buffer);
140 /* Common functions. */
142 /* Copies put_token, lexer->put_tokstr, put_tokval into token, tokstr,
143 tokval, respectively, and sets tokid appropriately. */
145 restore_token (struct lexer *lexer)
147 assert (lexer->put_token != 0);
148 lexer->token = lexer->put_token;
149 ds_assign_string (&lexer->tokstr, &lexer->put_tokstr);
150 str_copy_trunc (lexer->tokid, sizeof lexer->tokid, ds_cstr (&lexer->tokstr));
151 lexer->tokval = lexer->put_tokval;
152 lexer->put_token = 0;
155 /* Copies token, tokstr, lexer->tokval into lexer->put_token, put_tokstr,
156 put_lexer->tokval respectively. */
158 save_token (struct lexer *lexer)
160 lexer->put_token = lexer->token;
161 ds_assign_string (&lexer->put_tokstr, &lexer->tokstr);
162 lexer->put_tokval = lexer->tokval;
165 /* Parses a single token, setting appropriate global variables to
166 indicate the token's attributes. */
168 lex_get (struct lexer *lexer)
173 if (NULL == lexer->prog && ! lex_get_line (lexer) )
175 lexer->token = T_STOP;
179 /* If a token was pushed ahead, return it. */
180 if (lexer->put_token)
182 restore_token (lexer);
191 /* Skip whitespace. */
192 while (c_isspace ((unsigned char) *lexer->prog))
207 else if (!lex_get_line (lexer))
210 lexer->token = T_STOP;
217 if (lexer->put_token)
219 restore_token (lexer);
228 /* Actually parse the token. */
229 ds_clear (&lexer->tokstr);
231 switch (*lexer->prog)
234 case '0': case '1': case '2': case '3': case '4':
235 case '5': case '6': case '7': case '8': case '9':
239 /* `-' can introduce a negative number, or it can be a
240 token by itself. If it is not followed by a digit or a
241 decimal point, it is definitely not a number.
242 Otherwise, it might be either, but most of the time we
243 want it as a number. When the syntax calls for a `-'
244 token, lex_negative_to_dash() must be used to break
245 negative numbers into two tokens. */
246 if (*lexer->prog == '-')
248 ds_put_char (&lexer->tokstr, *lexer->prog++);
249 while (c_isspace ((unsigned char) *lexer->prog))
252 if (!c_isdigit ((unsigned char) *lexer->prog) && *lexer->prog != '.')
257 lexer->token = T_NEG_NUM;
260 lexer->token = T_POS_NUM;
262 /* Parse the number, copying it into tokstr. */
263 while (c_isdigit ((unsigned char) *lexer->prog))
264 ds_put_char (&lexer->tokstr, *lexer->prog++);
265 if (*lexer->prog == '.')
267 ds_put_char (&lexer->tokstr, *lexer->prog++);
268 while (c_isdigit ((unsigned char) *lexer->prog))
269 ds_put_char (&lexer->tokstr, *lexer->prog++);
271 if (*lexer->prog == 'e' || *lexer->prog == 'E')
273 ds_put_char (&lexer->tokstr, *lexer->prog++);
274 if (*lexer->prog == '+' || *lexer->prog == '-')
275 ds_put_char (&lexer->tokstr, *lexer->prog++);
276 while (c_isdigit ((unsigned char) *lexer->prog))
277 ds_put_char (&lexer->tokstr, *lexer->prog++);
280 /* Parse as floating point. */
281 lexer->tokval = c_strtod (ds_cstr (&lexer->tokstr), &tail);
284 msg (SE, _("%s does not form a valid number."),
285 ds_cstr (&lexer->tokstr));
288 ds_clear (&lexer->tokstr);
289 ds_put_char (&lexer->tokstr, '0');
296 lexer->token = parse_string (lexer, CHARACTER_STRING);
299 case '(': case ')': case ',': case '=': case '+': case '/':
301 lexer->token = *lexer->prog++;
305 if (*++lexer->prog == '*')
308 lexer->token = T_EXP;
315 if (*++lexer->prog == '=')
320 else if (*lexer->prog == '>')
330 if (*++lexer->prog == '=')
340 if (*++lexer->prog == '=')
346 lexer->token = T_NOT;
351 lexer->token = T_AND;
360 if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
361 lexer->token = parse_string (lexer, BINARY_STRING);
363 lexer->token = parse_id (lexer);
367 if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
368 lexer->token = parse_string (lexer, OCTAL_STRING);
370 lexer->token = parse_id (lexer);
374 if (lexer->prog[1] == '\'' || lexer->prog[1] == '"')
375 lexer->token = parse_string (lexer, HEX_STRING);
377 lexer->token = parse_id (lexer);
381 if (lex_is_id1 (*lexer->prog))
383 lexer->token = parse_id (lexer);
388 unsigned char c = *lexer->prog++;
389 char *c_name = xasprintf (c_isgraph (c) ? "%c" : "\\%o", c);
390 msg (SE, _("Bad character in input: `%s'."), c_name);
403 /* Parses an identifier at the current position into tokid and
405 Returns the correct token type. */
407 parse_id (struct lexer *lexer)
409 struct substring rest_of_line
410 = ss_substr (ds_ss (&lexer->line_buffer),
411 ds_pointer_to_position (&lexer->line_buffer, lexer->prog),
413 struct substring id = ss_head (rest_of_line,
414 lex_id_get_length (rest_of_line));
415 lexer->prog += ss_length (id);
417 ds_assign_substring (&lexer->tokstr, id);
418 str_copy_trunc (lexer->tokid, sizeof lexer->tokid, ds_cstr (&lexer->tokstr));
419 return lex_id_to_token (id);
422 /* Reports an error to the effect that subcommand SBC may only be
425 lex_sbc_only_once (const char *sbc)
427 msg (SE, _("Subcommand %s may only be specified once."), sbc);
430 /* Reports an error to the effect that subcommand SBC is
433 lex_sbc_missing (struct lexer *lexer, const char *sbc)
435 lex_error (lexer, _("missing required subcommand %s"), sbc);
438 /* Prints a syntax error message containing the current token and
439 given message MESSAGE (if non-null). */
441 lex_error (struct lexer *lexer, const char *message, ...)
446 token_rep = lex_token_representation (lexer);
447 if (lexer->token == T_STOP)
448 strcpy (where, "end of file");
449 else if (lexer->token == '.')
450 strcpy (where, "end of command");
452 snprintf (where, sizeof where, "`%s'", token_rep);
460 va_start (args, message);
461 vsnprintf (buf, 1024, message, args);
464 msg (SE, _("Syntax error %s at %s."), buf, where);
467 msg (SE, _("Syntax error at %s."), where);
470 /* Checks that we're at end of command.
471 If so, returns a successful command completion code.
472 If not, flags a syntax error and returns an error command
475 lex_end_of_command (struct lexer *lexer)
477 if (lexer->token != '.')
479 lex_error (lexer, _("expecting end of command"));
486 /* Token testing functions. */
488 /* Returns true if the current token is a number. */
490 lex_is_number (struct lexer *lexer)
492 return lexer->token == T_POS_NUM || lexer->token == T_NEG_NUM;
496 /* Returns true if the current token is a string. */
498 lex_is_string (struct lexer *lexer)
500 return lexer->token == T_STRING;
504 /* Returns the value of the current token, which must be a
505 floating point number. */
507 lex_number (struct lexer *lexer)
509 assert (lex_is_number (lexer));
510 return lexer->tokval;
513 /* Returns true iff the current token is an integer. */
515 lex_is_integer (struct lexer *lexer)
517 return (lex_is_number (lexer)
518 && lexer->tokval > LONG_MIN
519 && lexer->tokval <= LONG_MAX
520 && floor (lexer->tokval) == lexer->tokval);
523 /* Returns the value of the current token, which must be an
526 lex_integer (struct lexer *lexer)
528 assert (lex_is_integer (lexer));
529 return lexer->tokval;
532 /* Token matching functions. */
534 /* If TOK is the current token, skips it and returns true
535 Otherwise, returns false. */
537 lex_match (struct lexer *lexer, int t)
539 if (lexer->token == t)
548 /* If the current token is the identifier S, skips it and returns
549 true. The identifier may be abbreviated to its first three
551 Otherwise, returns false. */
553 lex_match_id (struct lexer *lexer, const char *s)
555 return lex_match_id_n (lexer, s, 3);
558 /* If the current token is the identifier S, skips it and returns
559 true. The identifier may be abbreviated to its first N
561 Otherwise, returns false. */
563 lex_match_id_n (struct lexer *lexer, const char *s, size_t n)
565 if (lexer->token == T_ID
566 && lex_id_match_n (ss_cstr (s), ss_cstr (lexer->tokid), n))
575 /* If the current token is integer N, skips it and returns true.
576 Otherwise, returns false. */
578 lex_match_int (struct lexer *lexer, int x)
580 if (lex_is_integer (lexer) && lex_integer (lexer) == x)
589 /* Forced matches. */
591 /* If this token is identifier S, fetches the next token and returns
593 Otherwise, reports an error and returns zero. */
595 lex_force_match_id (struct lexer *lexer, const char *s)
597 if (lex_match_id (lexer, s))
601 lex_error (lexer, _("expecting `%s'"), s);
606 /* If the current token is T, skips the token. Otherwise, reports an
607 error and returns from the current function with return value false. */
609 lex_force_match (struct lexer *lexer, int t)
611 if (lexer->token == t)
618 lex_error (lexer, _("expecting `%s'"), lex_token_name (t));
623 /* If this token is a string, does nothing and returns true.
624 Otherwise, reports an error and returns false. */
626 lex_force_string (struct lexer *lexer)
628 if (lexer->token == T_STRING)
632 lex_error (lexer, _("expecting string"));
637 /* If this token is an integer, does nothing and returns true.
638 Otherwise, reports an error and returns false. */
640 lex_force_int (struct lexer *lexer)
642 if (lex_is_integer (lexer))
646 lex_error (lexer, _("expecting integer"));
651 /* If this token is a number, does nothing and returns true.
652 Otherwise, reports an error and returns false. */
654 lex_force_num (struct lexer *lexer)
656 if (lex_is_number (lexer))
659 lex_error (lexer, _("expecting number"));
663 /* If this token is an identifier, does nothing and returns true.
664 Otherwise, reports an error and returns false. */
666 lex_force_id (struct lexer *lexer)
668 if (lexer->token == T_ID)
671 lex_error (lexer, _("expecting identifier"));
675 /* Weird token functions. */
677 /* Returns the first character of the next token, except that if the
678 next token is not an identifier, the character returned will not be
679 a character that can begin an identifier. Specifically, the
680 hexstring lead-in X' causes lookahead() to return '. Note that an
681 alphanumeric return value doesn't guarantee an ID token, it could
682 also be a reserved-word token. */
684 lex_look_ahead (struct lexer *lexer)
686 if (lexer->put_token)
687 return lexer->put_token;
691 if (NULL == lexer->prog && ! lex_get_line (lexer) )
696 while (c_isspace ((unsigned char) *lexer->prog))
703 else if (!lex_get_line (lexer))
706 if (lexer->put_token)
707 return lexer->put_token;
710 if ((toupper ((unsigned char) *lexer->prog) == 'X'
711 || toupper ((unsigned char) *lexer->prog) == 'B'
712 || toupper ((unsigned char) *lexer->prog) == 'O')
713 && (lexer->prog[1] == '\'' || lexer->prog[1] == '"'))
720 /* Makes the current token become the next token to be read; the
721 current token is set to T. */
723 lex_put_back (struct lexer *lexer, int t)
729 /* Makes the current token become the next token to be read; the
730 current token is set to the identifier ID. */
732 lex_put_back_id (struct lexer *lexer, const char *id)
734 assert (lex_id_to_token (ss_cstr (id)) == T_ID);
737 ds_assign_cstr (&lexer->tokstr, id);
738 str_copy_trunc (lexer->tokid, sizeof lexer->tokid, ds_cstr (&lexer->tokstr));
741 /* Weird line processing functions. */
743 /* Returns the entire contents of the current line. */
745 lex_entire_line (const struct lexer *lexer)
747 return ds_cstr (&lexer->line_buffer);
750 const struct string *
751 lex_entire_line_ds (const struct lexer *lexer)
753 return &lexer->line_buffer;
756 /* As lex_entire_line(), but only returns the part of the current line
757 that hasn't already been tokenized. */
759 lex_rest_of_line (const struct lexer *lexer)
764 /* Returns true if the current line ends in a terminal dot,
767 lex_end_dot (const struct lexer *lexer)
772 /* Causes the rest of the current input line to be ignored for
773 tokenization purposes. */
775 lex_discard_line (struct lexer *lexer)
777 ds_cstr (&lexer->line_buffer); /* Ensures ds_end points to something valid */
778 lexer->prog = ds_end (&lexer->line_buffer);
780 lexer->put_token = 0;
784 /* Discards the rest of the current command.
785 When we're reading commands from a file, we skip tokens until
786 a terminal dot or EOF.
787 When we're reading commands interactively from the user,
788 that's just discarding the current line, because presumably
789 the user doesn't want to finish typing a command that will be
792 lex_discard_rest_of_command (struct lexer *lexer)
794 if (!getl_is_interactive (lexer->ss))
796 while (lexer->token != T_STOP && lexer->token != '.')
800 lex_discard_line (lexer);
803 /* Weird line reading functions. */
805 /* Remove C-style comments in STRING, begun by slash-star and
806 terminated by star-slash or newline. */
808 strip_comments (struct string *string)
816 for (cp = ds_cstr (string); *cp; )
818 /* If we're not in a comment, check for quote marks. */
823 else if (*cp == '\'' || *cp == '"')
827 /* If we're not inside a quotation, check for comment. */
830 if (cp[0] == '/' && cp[1] == '*')
837 else if (in_comment && cp[0] == '*' && cp[1] == '/')
846 /* Check commenting. */
853 /* Prepares LINE, which is subject to the given SYNTAX rules, for
854 tokenization by stripping comments and determining whether it
855 is the beginning or end of a command and storing into
856 *LINE_STARTS_COMMAND and *LINE_ENDS_COMMAND appropriately. */
858 lex_preprocess_line (struct string *line,
859 enum syntax_mode syntax,
860 bool *line_starts_command,
861 bool *line_ends_command)
863 strip_comments (line);
864 ds_rtrim (line, ss_cstr (CC_SPACES));
865 *line_ends_command = (ds_chomp (line, settings_get_endcmd ())
866 || (ds_is_empty (line) && settings_get_nulline ()));
867 *line_starts_command = false;
868 if (syntax == GETL_BATCH)
870 int first = ds_first (line);
871 *line_starts_command = !c_isspace (first);
872 if (first == '+' || first == '-')
873 *ds_data (line) = ' ';
877 /* Reads a line, without performing any preprocessing. */
879 lex_get_line_raw (struct lexer *lexer)
881 bool ok = getl_read_line (lexer->ss, &lexer->line_buffer);
884 const char *line = ds_cstr (&lexer->line_buffer);
885 text_item_submit (text_item_create (TEXT_ITEM_SYNTAX, line));
890 /* Reads a line for use by the tokenizer, and preprocesses it by
891 removing comments, stripping trailing whitespace and the
892 terminal dot, and removing leading indentors. */
894 lex_get_line (struct lexer *lexer)
896 bool line_starts_command;
898 if (!lex_get_line_raw (lexer))
904 lex_preprocess_line (&lexer->line_buffer,
905 lex_current_syntax_mode (lexer),
906 &line_starts_command, &lexer->dot);
908 if (line_starts_command)
909 lexer->put_token = '.';
911 lexer->prog = ds_cstr (&lexer->line_buffer);
917 /* Returns the name of a token. */
919 lex_token_name (int token)
921 if (lex_is_keyword (token))
922 return lex_id_name (token);
923 else if (token < 256)
925 static char t[256][2];
935 /* Returns an ASCII representation of the current token as a
936 malloc()'d string. */
938 lex_token_representation (struct lexer *lexer)
942 switch (lexer->token)
947 return ds_xstrdup (&lexer->tokstr);
955 for (sp = ds_cstr (&lexer->tokstr); sp < ds_end (&lexer->tokstr); sp++)
956 if (!c_isprint ((unsigned char) *sp))
962 token_rep = xmalloc (2 + ds_length (&lexer->tokstr) * 2 + 1 + 1);
970 for (sp = ds_cstr (&lexer->tokstr); *sp; )
974 *dp++ = (unsigned char) *sp++;
977 for (sp = ds_cstr (&lexer->tokstr); sp < ds_end (&lexer->tokstr); sp++)
979 *dp++ = (((unsigned char) *sp) >> 4)["0123456789ABCDEF"];
980 *dp++ = (((unsigned char) *sp) & 15)["0123456789ABCDEF"];
990 token_rep = xmalloc (1);
995 return xstrdup ("**");
998 return xstrdup (lex_token_name (lexer->token));
1004 /* Really weird functions. */
1006 /* Most of the time, a `-' is a lead-in to a negative number. But
1007 sometimes it's actually part of the syntax. If a dash can be part
1008 of syntax then this function is called to rip it off of a
1011 lex_negative_to_dash (struct lexer *lexer)
1013 if (lexer->token == T_NEG_NUM)
1015 lexer->token = T_POS_NUM;
1016 lexer->tokval = -lexer->tokval;
1017 ds_assign_substring (&lexer->tokstr, ds_substr (&lexer->tokstr, 1, SIZE_MAX));
1023 /* Skip a COMMENT command. */
1025 lex_skip_comment (struct lexer *lexer)
1029 if (!lex_get_line (lexer))
1031 lexer->put_token = T_STOP;
1036 if (lexer->put_token == '.')
1039 ds_cstr (&lexer->line_buffer); /* Ensures ds_end will point to a valid char */
1040 lexer->prog = ds_end (&lexer->line_buffer);
1046 /* Private functions. */
1048 /* When invoked, tokstr contains a string of binary, octal, or
1049 hex digits, according to TYPE. The string is converted to
1050 characters having the specified values. */
1052 convert_numeric_string_to_char_string (struct lexer *lexer,
1053 enum string_type type)
1055 const char *base_name;
1065 base_name = _("binary");
1070 base_name = _("octal");
1075 base_name = _("hex");
1083 byte_cnt = ds_length (&lexer->tokstr) / chars_per_byte;
1084 if (ds_length (&lexer->tokstr) % chars_per_byte)
1085 msg (SE, _("String of %s digits has %zu characters, which is not a "
1087 base_name, ds_length (&lexer->tokstr), chars_per_byte);
1089 p = ds_cstr (&lexer->tokstr);
1090 for (i = 0; i < byte_cnt; i++)
1096 for (j = 0; j < chars_per_byte; j++, p++)
1100 if (*p >= '0' && *p <= '9')
1104 static const char alpha[] = "abcdef";
1105 const char *q = strchr (alpha, tolower ((unsigned char) *p));
1114 msg (SE, _("`%c' is not a valid %s digit."), *p, base_name);
1116 value = value * base + v;
1119 ds_cstr (&lexer->tokstr)[i] = (unsigned char) value;
1122 ds_truncate (&lexer->tokstr, byte_cnt);
1125 /* Parses a string from the input buffer into tokstr. The input
1126 buffer pointer lexer->prog must point to the initial single or double
1127 quote. TYPE indicates the type of string to be parsed.
1128 Returns token type. */
1130 parse_string (struct lexer *lexer, enum string_type type)
1132 if (type != CHARACTER_STRING)
1135 /* Accumulate the entire string, joining sections indicated by +
1139 /* Single or double quote. */
1140 int c = *lexer->prog++;
1142 /* Accumulate section. */
1145 /* Check end of line. */
1146 if (*lexer->prog == '\0')
1148 msg (SE, _("Unterminated string constant."));
1152 /* Double quote characters to embed them in strings. */
1153 if (*lexer->prog == c)
1155 if (lexer->prog[1] == c)
1161 ds_put_char (&lexer->tokstr, *lexer->prog++);
1165 /* Skip whitespace after final quote mark. */
1166 if (lexer->prog == NULL)
1170 while (c_isspace ((unsigned char) *lexer->prog))
1178 if (!lex_get_line (lexer))
1182 /* Skip plus sign. */
1183 if (*lexer->prog != '+')
1187 /* Skip whitespace after plus sign. */
1188 if (lexer->prog == NULL)
1192 while (c_isspace ((unsigned char) *lexer->prog))
1200 if (!lex_get_line (lexer))
1202 msg (SE, _("Unexpected end of file in string concatenation."));
1207 /* Ensure that a valid string follows. */
1208 if (*lexer->prog != '\'' && *lexer->prog != '"')
1210 msg (SE, _("String expected following `+'."));
1215 /* We come here when we've finished concatenating all the string sections
1216 into one large string. */
1218 if (type != CHARACTER_STRING)
1219 convert_numeric_string_to_char_string (lexer, type);
1225 /* Reads one token from the lexer and writes a textual representation
1226 on stdout for debugging purposes. */
1228 dump_token (struct lexer *lexer)
1234 curln = getl_source_location (lexer->ss);
1235 curfn = getl_source_name (lexer->ss);
1237 fprintf (stderr, "%s:%d\t", curfn, curln);
1240 switch (lexer->token)
1243 fprintf (stderr, "ID\t%s\n", lexer->tokid);
1248 fprintf (stderr, "NUM\t%f\n", lexer->tokval);
1252 fprintf (stderr, "STRING\t\"%s\"\n", ds_cstr (&lexer->tokstr));
1256 fprintf (stderr, "STOP\n");
1260 fprintf (stderr, "MISC\tEXP\"");
1264 fprintf (stderr, "MISC\tEOF\n");
1268 if (lex_is_keyword (lexer->token))
1269 fprintf (stderr, "KEYWORD\t%s\n", lex_token_name (lexer->token));
1271 fprintf (stderr, "PUNCT\t%c\n", lexer->token);
1275 #endif /* DUMP_TOKENS */
1278 /* Token Accessor Functions */
1281 lex_token (const struct lexer *lexer)
1283 return lexer->token;
1287 lex_tokval (const struct lexer *lexer)
1289 return lexer->tokval;
1293 lex_tokid (const struct lexer *lexer)
1295 return lexer->tokid;
1298 const struct string *
1299 lex_tokstr (const struct lexer *lexer)
1301 return &lexer->tokstr;
1304 /* If the lexer is positioned at the (pseudo)identifier S, which
1305 may contain a hyphen ('-'), skips it and returns true. Each
1306 half of the identifier may be abbreviated to its first three
1308 Otherwise, returns false. */
1310 lex_match_hyphenated_word (struct lexer *lexer, const char *s)
1312 const char *hyphen = strchr (s, '-');
1314 return lex_match_id (lexer, s);
1315 else if (lexer->token != T_ID
1316 || !lex_id_match (ss_buffer (s, hyphen - s), ss_cstr (lexer->tokid))
1317 || lex_look_ahead (lexer) != '-')
1322 lex_force_match (lexer, '-');
1323 lex_force_match_id (lexer, hyphen + 1);