1
1
#include " rust-cfg-parser.h"
2
+ #include " rust-lex.h"
3
+ #include " rust-parse.h"
4
+ #include " rust-session-manager.h"
2
5
#include " selftest.h"
3
6
4
7
namespace Rust {
5
8
bool
6
- parse_cfg_option (const std::string &input, std::string &key,
7
- std::string &value)
9
+ parse_cfg_option (std::string &input, std::string &key, std::string &value)
8
10
{
9
11
key.clear ();
10
12
value.clear ();
11
13
12
- auto equal = input.find (' =' );
14
+ auto lexer = Lexer::lex_string (input);
15
+ auto parser = Parser<Lexer> (std::move (lexer));
13
16
14
- // If there is no equal sign, it means there is no value. Clean up the key
15
- // and return
16
- if (equal == std::string::npos)
17
+ auto token = parser.peek_current_token ();
18
+ if (token->get_id () != IDENTIFIER)
17
19
{
18
- key = input;
19
-
20
- // FIXME: Make sure key is a proper identifier
21
-
22
- return true ;
20
+ return false ;
23
21
}
24
22
25
- key = input.substr (0 , equal);
26
-
27
- auto remaining_input = input.substr (equal + 1 );
28
- if (remaining_input[0 ] != ' "' || remaining_input.back () != ' "' )
29
- return false ;
30
-
31
- // Remove the quotes around the value, by advancing one character
32
- value = remaining_input.substr (1 );
33
- // And trimming the rightmost character. This is fine since we've already
34
- // checked that both the first and last characters were quotes.
35
- value.resize (value.size () - 1 );
23
+ key = token->get_str ();
36
24
37
- // FIXME: We need to sanitize here and make sure that both key and value
38
- // are proper identifiers
25
+ rust_assert (parser. skip_token (IDENTIFIER));
26
+ token = parser. peek_current_token ();
39
27
40
- return true ;
28
+ switch (token->get_id ())
29
+ {
30
+ case END_OF_FILE:
31
+ // we're done parsing, we had a valid key, return happily
32
+ return true ;
33
+ case EQUAL:
34
+ // We have an equal sign: Skip the token and parse an identifier
35
+ {
36
+ rust_assert (parser.skip_token (EQUAL));
37
+
38
+ auto value_expr = parser.parse_literal_expr ();
39
+ // We had an equal sign but no value, error out
40
+ if (!value_expr)
41
+ return false ;
42
+
43
+ if (value_expr->get_lit_type () != AST::Literal::LitType::STRING)
44
+ return false ;
45
+
46
+ value = value_expr->get_literal ().as_string ();
47
+ return true ;
48
+ }
49
+ default :
50
+ return false ;
51
+ }
41
52
}
42
-
43
53
} // namespace Rust
44
54
45
55
#if CHECKING_P
@@ -52,23 +62,49 @@ rust_cfg_parser_test (void)
52
62
std::string key;
53
63
std::string value;
54
64
55
- ASSERT_TRUE (Rust::parse_cfg_option (" key-no-value" , key, value));
56
- ASSERT_EQ (key, " key-no-value" );
65
+ auto input = std::string (" key_no_value" );
66
+
67
+ ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
68
+ ASSERT_EQ (key, " key_no_value" );
57
69
ASSERT_TRUE (value.empty ());
58
70
59
- ASSERT_TRUE (Rust::parse_cfg_option (" k=\" v\" " , key, value));
71
+ input = std::string (" k=\" v\" " );
72
+
73
+ ASSERT_TRUE (Rust::parse_cfg_option (input, key, value));
60
74
ASSERT_EQ (key, " k" );
61
75
ASSERT_EQ (value, " v" );
62
76
63
77
// values should be between double quotes
64
- ASSERT_FALSE (Rust::parse_cfg_option (" k=v" , key, value));
78
+ input = std::string (" k=v" );
79
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
65
80
66
81
// No value is an error if there is an equal sign
67
- ASSERT_FALSE (Rust::parse_cfg_option (" k=" , key, value));
82
+ input = std::string (" k=" );
83
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
68
84
69
85
// No key is an error
70
- ASSERT_FALSE (Rust::parse_cfg_option (" =" , key, value));
71
- ASSERT_FALSE (Rust::parse_cfg_option (" =value" , key, value));
86
+ input = std::string (" =" );
87
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
88
+
89
+ input = std::string (" =value" );
90
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
91
+
92
+ // values that are not string literals are an error
93
+ input = std::string (" key=b\" a\" " );
94
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
95
+
96
+ input = std::string (" key='v'" );
97
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
98
+
99
+ input = std::string (" key=155" );
100
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
101
+
102
+ input = std::string (" key=3.14" );
103
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
104
+
105
+ // kebab case is not valid for an identifier
106
+ input = std::string (" key-no-value" );
107
+ ASSERT_FALSE (Rust::parse_cfg_option (input, key, value));
72
108
}
73
109
} // namespace selftest
74
110
0 commit comments