2

私はproc_macro2/synマクロに取り組んでおりCursor、何かの低レベルの解析を行うために使用しています... Rust- like . しかし、私の文法の奥深くでは、 a を解析する必要がありsyn::Typeます。私の知る限り、これを行う唯一の本当に良い方法は、 for を使用することimpl syn::parse::Parseですsyn::Type

だから私が本当に見つけたいのは、署名の関数を書く良い方法です

fn parse_generic<T: Parse>(c: Cursor) -> Option<(T, Cursor)>;

私の質問は、このタイプの関数を実装するための最良の (最も簡単で、問題の少ない) 方法は何ですか?


これが私がこれまでに思いついた最高のものです:

fn parse_generic<T: Parse>(mut c: Cursor) -> Option<(T, Cursor)> {                                                                       
    match T::parse.parse2(c.token_stream()) {                                                                                            
        Ok(t) => Some((t, Cursor::empty())), // because parse2 checks for end-of-stream!                                                 
        Err(e) => {                                                                                                                      
            // OK, because parse2 checks for end-of-stream, let's chop                                                                   
            // the input at the position of the error and try again (!).                                                                 
            let mut collected = Vec::new();                                                                                              
            let upto = e.span().start();                                                                                                 
            while !c.eof() && c.span().start() != upto {                                                                                 
                let (tt, next) = c.token_tree().unwrap();                                                                                
                collected.push(tt);                                                                                                      
                c = next;                                                                                                                
            }                                                                                                                            
            match T::parse.parse2(collected.into_iter().collect()) {                                                                     
                Ok(t) => Some((t, c)),                                                                                                   
                Err(_) => None,                                                                                                          
            }                                                                                                                            
        }                                                                                                                                
    }                                                                                                                                    
}                                                                                                                                        

悲惨なことではありませんが、理想的でもありません。

4

0 に答える 0