1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000, 2005 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 This file is concerned with the definition of the PSPP syntax, NOT the
21 action of scanning/parsing code .
25 #include "identifier.h"
30 #include <libpspp/assertion.h>
32 /* Recognizing identifiers. */
34 /* Returns true if C may be the first character in an
35 identifier in the current locale. */
40 return isalpha (c) || c == '@' || c == '#' || c == '$';
44 /* Returns true if C may be a character in an identifier other
50 return lex_is_id1 (c) || isdigit (c) || c == '.' || c == '_';
53 /* Returns the length of the longest prefix of STRING that forms
54 a valid identifier. Returns zero if STRING does not begin
55 with a valid identifier. */
57 lex_id_get_length (struct substring string)
60 if (!ss_is_empty (string) && lex_is_id1 (ss_first (string)))
63 while (length < ss_length (string)
64 && lex_is_idn (ss_at (string, length)))
70 /* Comparing identifiers. */
72 /* Returns true if TOKEN is a case-insensitive match for KEYWORD.
74 Keywords match if one of the following is true: KEYWORD and
75 TOKEN are identical, or TOKEN is at least 3 characters long
76 and those characters are identical to KEYWORD. */
78 lex_id_match (struct substring keyword, struct substring token)
80 size_t token_len = ss_length (token);
81 size_t keyword_len = ss_length (keyword);
83 if (token_len >= 3 && token_len < keyword_len)
84 return ss_equals_case (ss_head (keyword, token_len), token);
86 return ss_equals_case (keyword, token);
89 /* Table of keywords. */
93 const struct substring identifier;
96 static const struct keyword keywords[] =
98 { T_AND, SS_LITERAL_INITIALIZER ("AND") },
99 { T_OR, SS_LITERAL_INITIALIZER ("OR") },
100 { T_NOT, SS_LITERAL_INITIALIZER ("NOT") },
101 { T_EQ, SS_LITERAL_INITIALIZER ("EQ") },
102 { T_GE, SS_LITERAL_INITIALIZER ("GE") },
103 { T_GT, SS_LITERAL_INITIALIZER ("GT") },
104 { T_LE, SS_LITERAL_INITIALIZER ("LE") },
105 { T_LT, SS_LITERAL_INITIALIZER ("LT") },
106 { T_NE, SS_LITERAL_INITIALIZER ("NE") },
107 { T_ALL, SS_LITERAL_INITIALIZER ("ALL") },
108 { T_BY, SS_LITERAL_INITIALIZER ("BY") },
109 { T_TO, SS_LITERAL_INITIALIZER ("TO") },
110 { T_WITH, SS_LITERAL_INITIALIZER ("WITH") },
112 static const size_t keyword_cnt = sizeof keywords / sizeof *keywords;
114 /* Returns true if TOKEN is representable as a keyword. */
116 lex_is_keyword (int token)
118 const struct keyword *kw;
119 for (kw = keywords; kw < &keywords[keyword_cnt]; kw++)
120 if (kw->token == token)
125 /* Returns the proper token type, either T_ID or a reserved
126 keyword enum, for ID. */
128 lex_id_to_token (struct substring id)
130 if (ss_length (id) >= 2 && ss_length (id) <= 4)
132 const struct keyword *kw;
133 for (kw = keywords; kw < &keywords[keyword_cnt]; kw++)
134 if (ss_equals_case (kw->identifier, id))
141 /* Returns the name for the given keyword token type. */
143 lex_id_name (int token)
145 const struct keyword *kw;
147 for (kw = keywords; kw < &keywords[keyword_cnt]; kw++)
148 if (kw->token == token)
150 /* A "struct substring" is not guaranteed to be
151 null-terminated, as our caller expects, but in this
152 case it always will be. */
153 return ss_data (kw->identifier);