diff options
author | Adolfo OchagavĂa <[email protected]> | 2018-11-11 19:41:43 +0000 |
---|---|---|
committer | Adolfo OchagavĂa <[email protected]> | 2018-11-11 19:41:43 +0000 |
commit | 30cd4d5acb7dfd40cea264a926d1c89f0c3522c3 (patch) | |
tree | d71024919de98d74bf1a6bedc8a755c8810f1723 /crates/ra_syntax/src/string_lexing.rs | |
parent | c258b4fdb0e421813330c2428985c4537c787582 (diff) |
Validate byte string literals
Diffstat (limited to 'crates/ra_syntax/src/string_lexing.rs')
-rw-r--r-- | crates/ra_syntax/src/string_lexing.rs | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/crates/ra_syntax/src/string_lexing.rs b/crates/ra_syntax/src/string_lexing.rs index 4e8c3a91c..d253c97e7 100644 --- a/crates/ra_syntax/src/string_lexing.rs +++ b/crates/ra_syntax/src/string_lexing.rs | |||
@@ -1,6 +1,55 @@ | |||
1 | use self::CharComponentKind::*; | 1 | use self::CharComponentKind::*; |
2 | use rowan::{TextRange, TextUnit}; | 2 | use rowan::{TextRange, TextUnit}; |
3 | 3 | ||
4 | pub fn parse_byte_string_literal(src: &str) -> ByteStringComponentIterator { | ||
5 | ByteStringComponentIterator { | ||
6 | parser: Parser::new(src), | ||
7 | has_closing_quote: false, | ||
8 | } | ||
9 | } | ||
10 | |||
11 | pub struct ByteStringComponentIterator<'a> { | ||
12 | parser: Parser<'a>, | ||
13 | pub has_closing_quote: bool, | ||
14 | } | ||
15 | |||
16 | impl<'a> Iterator for ByteStringComponentIterator<'a> { | ||
17 | type Item = StringComponent; | ||
18 | fn next(&mut self) -> Option<StringComponent> { | ||
19 | if self.parser.pos == 0 { | ||
20 | assert!( | ||
21 | self.parser.advance() == 'b', | ||
22 | "byte string literal should start with a `b`" | ||
23 | ); | ||
24 | |||
25 | assert!( | ||
26 | self.parser.advance() == '"', | ||
27 | "byte string literal should start with a `b`, followed by double quotes" | ||
28 | ); | ||
29 | } | ||
30 | |||
31 | if let Some(component) = self.parser.parse_string_component() { | ||
32 | return Some(component); | ||
33 | } | ||
34 | |||
35 | // We get here when there are no char components left to parse | ||
36 | if self.parser.peek() == Some('"') { | ||
37 | self.parser.advance(); | ||
38 | self.has_closing_quote = true; | ||
39 | } | ||
40 | |||
41 | assert!( | ||
42 | self.parser.peek() == None, | ||
43 | "byte string literal should leave no unparsed input: src = {}, pos = {}, length = {}", | ||
44 | self.parser.src, | ||
45 | self.parser.pos, | ||
46 | self.parser.src.len() | ||
47 | ); | ||
48 | |||
49 | None | ||
50 | } | ||
51 | } | ||
52 | |||
4 | pub fn parse_string_literal(src: &str) -> StringComponentIterator { | 53 | pub fn parse_string_literal(src: &str) -> StringComponentIterator { |
5 | StringComponentIterator { | 54 | StringComponentIterator { |
6 | parser: Parser::new(src), | 55 | parser: Parser::new(src), |
@@ -81,12 +130,12 @@ impl<'a> Iterator for ByteComponentIterator<'a> { | |||
81 | if self.parser.pos == 0 { | 130 | if self.parser.pos == 0 { |
82 | assert!( | 131 | assert!( |
83 | self.parser.advance() == 'b', | 132 | self.parser.advance() == 'b', |
84 | "Byte literal should start with a b" | 133 | "Byte literal should start with a `b`" |
85 | ); | 134 | ); |
86 | 135 | ||
87 | assert!( | 136 | assert!( |
88 | self.parser.advance() == '\'', | 137 | self.parser.advance() == '\'', |
89 | "Byte literal should start with a b, followed by a quote" | 138 | "Byte literal should start with a `b`, followed by a quote" |
90 | ); | 139 | ); |
91 | } | 140 | } |
92 | 141 | ||