Line data Source code
1 : /* This file is part of GCC.
2 :
3 : GCC is free software; you can redistribute it and/or modify
4 : it under the terms of the GNU General Public License as published by
5 : the Free Software Foundation; either version 3, or (at your option)
6 : any later version.
7 :
8 : GCC is distributed in the hope that it will be useful,
9 : but WITHOUT ANY WARRANTY; without even the implied warranty of
10 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 : GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License
14 : along with GCC; see the file COPYING3. If not see
15 : <http://www.gnu.org/licenses/>. */
16 :
17 : #include "rust-cfg-parser.h"
18 : #include "rust-lex.h"
19 : #include "rust-parse.h"
20 : #include "rust-session-manager.h"
21 : #include "selftest.h"
22 :
23 : namespace Rust {
24 : bool
25 79 : parse_cfg_option (std::string &input, std::string &key, std::string &value)
26 : {
27 79 : key.clear ();
28 79 : value.clear ();
29 :
30 79 : auto lexer = Lexer (input, nullptr);
31 79 : auto parser = Parser<Lexer> (lexer);
32 :
33 79 : auto token = parser.peek_current_token ();
34 79 : if (token->get_id () != IDENTIFIER)
35 : {
36 : return false;
37 : }
38 :
39 77 : key = token->get_str ();
40 :
41 77 : rust_assert (parser.skip_token (IDENTIFIER));
42 77 : token = parser.peek_current_token ();
43 :
44 77 : switch (token->get_id ())
45 : {
46 : case END_OF_FILE:
47 : // we're done parsing, we had a valid key, return happily
48 : return true;
49 9 : case EQUAL:
50 : // We have an equal sign: Skip the token and parse an identifier
51 9 : {
52 9 : rust_assert (parser.skip_token (EQUAL));
53 :
54 9 : auto value_expr_res = parser.parse_literal_expr ();
55 : // We had an equal sign but no value, error out
56 9 : if (!value_expr_res)
57 : return false;
58 7 : auto value_expr = std::move (value_expr_res.value ());
59 :
60 7 : if (value_expr->get_lit_type () != AST::Literal::LitType::STRING)
61 : return false;
62 :
63 6 : value = value_expr->get_literal ().as_string ();
64 3 : return true;
65 16 : }
66 : default:
67 : return false;
68 : }
69 158 : }
70 : } // namespace Rust
71 :
72 : #if CHECKING_P
73 :
74 : namespace selftest {
75 :
76 : void
77 1 : rust_cfg_parser_test (void)
78 : {
79 1 : std::string key;
80 1 : std::string value;
81 :
82 1 : auto input = std::string ("key_no_value");
83 :
84 1 : ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
85 1 : ASSERT_EQ (key, "key_no_value");
86 1 : ASSERT_TRUE (value.empty ());
87 :
88 1 : input = std::string ("k=\"v\"");
89 :
90 1 : ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
91 1 : ASSERT_EQ (key, "k");
92 1 : ASSERT_EQ (value, "v");
93 :
94 : // values should be between double quotes
95 1 : input = std::string ("k=v");
96 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
97 :
98 : // No value is an error if there is an equal sign
99 1 : input = std::string ("k=");
100 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
101 :
102 : // No key is an error
103 1 : input = std::string ("=");
104 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
105 :
106 1 : input = std::string ("=value");
107 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
108 :
109 : // values that are not string literals are an error
110 1 : input = std::string ("key=b\"a\"");
111 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
112 :
113 1 : input = std::string ("key='v'");
114 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
115 :
116 1 : input = std::string ("key=155");
117 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
118 :
119 1 : input = std::string ("key=3.14");
120 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
121 :
122 : // kebab case is not valid for an identifier
123 1 : input = std::string ("key-no-value");
124 1 : ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
125 1 : }
126 : } // namespace selftest
127 :
128 : #endif // CHECKING_P
|