1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use parse
::{ParseSess,PResult,filemap_to_tts}
;
13 use parse
::{lexer, new_parser_from_source_str}
;
14 use parse
::parser
::Parser
;
17 use std
::iter
::Peekable
;
19 /// Map a string to tts, using a made-up filename:
20 pub fn string_to_tts(source_str
: String
) -> Vec
<ast
::TokenTree
> {
21 let ps
= ParseSess
::new();
22 filemap_to_tts(&ps
, ps
.codemap().new_filemap("bogofile".to_string(), source_str
))
25 /// Map string to parser (via tts)
26 pub fn string_to_parser
<'a
>(ps
: &'a ParseSess
, source_str
: String
) -> Parser
<'a
> {
27 new_parser_from_source_str(ps
,
29 "bogofile".to_string(),
33 fn with_error_checking_parse
<'a
, T
, F
>(s
: String
, ps
: &'a ParseSess
, f
: F
) -> T
where
34 F
: FnOnce(&mut Parser
<'a
>) -> PResult
<'a
, T
>,
36 let mut p
= string_to_parser(&ps
, s
);
37 let x
= panictry
!(f(&mut p
));
42 /// Parse a string, return a crate.
43 pub fn string_to_crate (source_str
: String
) -> ast
::Crate
{
44 let ps
= ParseSess
::new();
45 with_error_checking_parse(source_str
, &ps
, |p
| {
50 /// Parse a string, return an expr
51 pub fn string_to_expr (source_str
: String
) -> P
<ast
::Expr
> {
52 let ps
= ParseSess
::new();
53 with_error_checking_parse(source_str
, &ps
, |p
| {
58 /// Parse a string, return an item
59 pub fn string_to_item (source_str
: String
) -> Option
<P
<ast
::Item
>> {
60 let ps
= ParseSess
::new();
61 with_error_checking_parse(source_str
, &ps
, |p
| {
66 /// Parse a string, return a stmt
67 pub fn string_to_stmt(source_str
: String
) -> Option
<ast
::Stmt
> {
68 let ps
= ParseSess
::new();
69 with_error_checking_parse(source_str
, &ps
, |p
| {
74 /// Parse a string, return a pat. Uses "irrefutable"... which doesn't
75 /// (currently) affect parsing.
76 pub fn string_to_pat(source_str
: String
) -> P
<ast
::Pat
> {
77 let ps
= ParseSess
::new();
78 with_error_checking_parse(source_str
, &ps
, |p
| {
83 /// Convert a vector of strings to a vector of ast::Ident's
84 pub fn strs_to_idents(ids
: Vec
<&str> ) -> Vec
<ast
::Ident
> {
85 ids
.iter().map(|u
| token
::str_to_ident(*u
)).collect()
88 /// Does the given string match the pattern? whitespace in the first string
89 /// may be deleted or replaced with other whitespace to match the pattern.
90 /// This function is relatively Unicode-ignorant; fortunately, the careful design
91 /// of UTF-8 mitigates this ignorance. It doesn't do NKF-normalization(?).
92 pub fn matches_codepattern(a
: &str, b
: &str) -> bool
{
93 let mut a_iter
= a
.chars().peekable();
94 let mut b_iter
= b
.chars().peekable();
97 let (a
, b
) = match (a_iter
.peek(), b_iter
.peek()) {
98 (None
, None
) => return true,
99 (None
, _
) => return false,
100 (Some(&a
), None
) => {
101 if is_pattern_whitespace(a
) {
102 break // trailing whitespace check is out of loop for borrowck
107 (Some(&a
), Some(&b
)) => (a
, b
)
110 if is_pattern_whitespace(a
) && is_pattern_whitespace(b
) {
111 // skip whitespace for a and b
112 scan_for_non_ws_or_end(&mut a_iter
);
113 scan_for_non_ws_or_end(&mut b_iter
);
114 } else if is_pattern_whitespace(a
) {
115 // skip whitespace for a
116 scan_for_non_ws_or_end(&mut a_iter
);
125 // check if a has *only* trailing whitespace
126 a_iter
.all(is_pattern_whitespace
)
129 /// Advances the given peekable `Iterator` until it reaches a non-whitespace character
130 fn scan_for_non_ws_or_end
<I
: Iterator
<Item
= char>>(iter
: &mut Peekable
<I
>) {
131 while lexer
::is_pattern_whitespace(iter
.peek().cloned()) {
136 pub fn is_pattern_whitespace(c
: char) -> bool
{
137 lexer
::is_pattern_whitespace(Some(c
))
146 assert_eq
!(matches_codepattern("",""),true);
147 assert_eq
!(matches_codepattern("","a"),false);
148 assert_eq
!(matches_codepattern("a",""),false);
149 assert_eq
!(matches_codepattern("a","a"),true);
150 assert_eq
!(matches_codepattern("a b","a \n\t\r b"),true);
151 assert_eq
!(matches_codepattern("a b ","a \n\t\r b"),true);
152 assert_eq
!(matches_codepattern("a b","a \n\t\r b "),false);
153 assert_eq
!(matches_codepattern("a b","a b"),true);
154 assert_eq
!(matches_codepattern("ab","a b"),false);
155 assert_eq
!(matches_codepattern("a b","ab"),true);
156 assert_eq
!(matches_codepattern(" a b","ab"),true);
160 fn pattern_whitespace() {
161 assert_eq
!(matches_codepattern("","\x0C"), false);
162 assert_eq
!(matches_codepattern("a b ","a \u{0085}\n\t\r b"),true);
163 assert_eq
!(matches_codepattern("a b","a \u{0085}\n\t\r b "),false);
167 fn non_pattern_whitespace() {
168 // These have the property 'White_Space' but not 'Pattern_White_Space'
169 assert_eq
!(matches_codepattern("a b","a\u{2002}b"), false);
170 assert_eq
!(matches_codepattern("a b","a\u{2002}b"), false);
171 assert_eq
!(matches_codepattern("\u{205F}a b","ab"), false);
172 assert_eq
!(matches_codepattern("a \u{3000}b","ab"), false);