1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2005 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/>. */
18 This file is concerned with the definition of the PSPP syntax, NOT the
19 action of scanning/parsing code .
23 #include "identifier.h"
28 #include <libpspp/assertion.h>
30 /* Recognizing identifiers. */
32 /* Returns true if C may be the first character in an
33 identifier in the current locale. */
38 return isalpha (c) || c == '@' || c == '#' || c == '$';
42 /* Returns true if C may be a character in an identifier other
48 return lex_is_id1 (c) || isdigit (c) || c == '.' || c == '_';
51 /* Returns the length of the longest prefix of STRING that forms
52 a valid identifier. Returns zero if STRING does not begin
53 with a valid identifier. */
55 lex_id_get_length (struct substring string)
58 if (!ss_is_empty (string) && lex_is_id1 (ss_first (string)))
61 while (length < ss_length (string)
62 && lex_is_idn (ss_at (string, length)))
68 /* Comparing identifiers. */
70 /* Returns true if TOKEN is a case-insensitive match for KEYWORD.
72 Keywords match if one of the following is true: KEYWORD and
73 TOKEN are identical, or TOKEN is at least 3 characters long
74 and those characters are identical to KEYWORD. */
76 lex_id_match (struct substring keyword, struct substring token)
78 size_t token_len = ss_length (token);
79 size_t keyword_len = ss_length (keyword);
81 if (token_len >= 3 && token_len < keyword_len)
82 return ss_equals_case (ss_head (keyword, token_len), token);
84 return ss_equals_case (keyword, token);
87 /* Table of keywords. */
91 const struct substring identifier;
94 static const struct keyword keywords[] =
96 { T_AND, SS_LITERAL_INITIALIZER ("AND") },
97 { T_OR, SS_LITERAL_INITIALIZER ("OR") },
98 { T_NOT, SS_LITERAL_INITIALIZER ("NOT") },
99 { T_EQ, SS_LITERAL_INITIALIZER ("EQ") },
100 { T_GE, SS_LITERAL_INITIALIZER ("GE") },
101 { T_GT, SS_LITERAL_INITIALIZER ("GT") },
102 { T_LE, SS_LITERAL_INITIALIZER ("LE") },
103 { T_LT, SS_LITERAL_INITIALIZER ("LT") },
104 { T_NE, SS_LITERAL_INITIALIZER ("NE") },
105 { T_ALL, SS_LITERAL_INITIALIZER ("ALL") },
106 { T_BY, SS_LITERAL_INITIALIZER ("BY") },
107 { T_TO, SS_LITERAL_INITIALIZER ("TO") },
108 { T_WITH, SS_LITERAL_INITIALIZER ("WITH") },
110 static const size_t keyword_cnt = sizeof keywords / sizeof *keywords;
112 /* Returns true if TOKEN is representable as a keyword. */
114 lex_is_keyword (int token)
116 const struct keyword *kw;
117 for (kw = keywords; kw < &keywords[keyword_cnt]; kw++)
118 if (kw->token == token)
123 /* Returns the proper token type, either T_ID or a reserved
124 keyword enum, for ID. */
126 lex_id_to_token (struct substring id)
128 if (ss_length (id) >= 2 && ss_length (id) <= 4)
130 const struct keyword *kw;
131 for (kw = keywords; kw < &keywords[keyword_cnt]; kw++)
132 if (ss_equals_case (kw->identifier, id))
139 /* Returns the name for the given keyword token type. */
141 lex_id_name (int token)
143 const struct keyword *kw;
145 for (kw = keywords; kw < &keywords[keyword_cnt]; kw++)
146 if (kw->token == token)
148 /* A "struct substring" is not guaranteed to be
149 null-terminated, as our caller expects, but in this
150 case it always will be. */
151 return ss_data (kw->identifier);