]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/rust/parse/rust-cfg-parser.cc
gccrs: Add Parser for Rust front-end pt.1
[thirdparty/gcc.git] / gcc / rust / parse / rust-cfg-parser.cc
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 parse_cfg_option (std::string &input, std::string &key, std::string &value)
26 {
27 key.clear ();
28 value.clear ();
29
30 auto lexer = Lexer (input);
31 auto parser = Parser<Lexer> (lexer);
32
33 auto token = parser.peek_current_token ();
34 if (token->get_id () != IDENTIFIER)
35 {
36 return false;
37 }
38
39 key = token->get_str ();
40
41 rust_assert (parser.skip_token (IDENTIFIER));
42 token = parser.peek_current_token ();
43
44 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 case EQUAL:
50 // We have an equal sign: Skip the token and parse an identifier
51 {
52 rust_assert (parser.skip_token (EQUAL));
53
54 auto value_expr = parser.parse_literal_expr ();
55 // We had an equal sign but no value, error out
56 if (!value_expr)
57 return false;
58
59 if (value_expr->get_lit_type () != AST::Literal::LitType::STRING)
60 return false;
61
62 value = value_expr->get_literal ().as_string ();
63 return true;
64 }
65 default:
66 return false;
67 }
68 }
69 } // namespace Rust
70
71 #if CHECKING_P
72
73 namespace selftest {
74
75 void
76 rust_cfg_parser_test (void)
77 {
78 std::string key;
79 std::string value;
80
81 auto input = std::string ("key_no_value");
82
83 ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
84 ASSERT_EQ (key, "key_no_value");
85 ASSERT_TRUE (value.empty ());
86
87 input = std::string ("k=\"v\"");
88
89 ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
90 ASSERT_EQ (key, "k");
91 ASSERT_EQ (value, "v");
92
93 // values should be between double quotes
94 input = std::string ("k=v");
95 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
96
97 // No value is an error if there is an equal sign
98 input = std::string ("k=");
99 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
100
101 // No key is an error
102 input = std::string ("=");
103 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
104
105 input = std::string ("=value");
106 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
107
108 // values that are not string literals are an error
109 input = std::string ("key=b\"a\"");
110 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
111
112 input = std::string ("key='v'");
113 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
114
115 input = std::string ("key=155");
116 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
117
118 input = std::string ("key=3.14");
119 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
120
121 // kebab case is not valid for an identifier
122 input = std::string ("key-no-value");
123 ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
124 }
125 } // namespace selftest
126
127 #endif // CHECKING_P