Struct ParseStream

Source
pub struct ParseStream<'a> { /* private fields */ }

Implementations§

Source§

impl<'a> ParseStream<'a>

Source

pub fn new(slice: &'a str) -> ParseStream<'a>

Source

pub fn empty() -> ParseStream<'a>

Source

pub fn snapshot(&self) -> Snapshot

Examples found in repository?
examples/tokenizer.rs (line 100)
98    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
99        stream.try_parse(|stream| {
100            let snap = stream.snapshot();
101            let mut first_c = false;
102            let slice = stream.cur().advance_while(|c| {
103                if first_c {
104                    first_c = false;
105                    UnicodeXID::is_xid_start(c)
106                } else {
107                    UnicodeXID::is_xid_continue(c)
108                }
109            });
110            if slice.is_empty() {
111                Err("Expected identifier.")
112            } else {
113                Ok(Ident {
114                    string: String::from(slice),
115                    span: stream.since(snap),
116                })
117            }
118        })
119    }
Source

pub fn since(&self, snapshot: Snapshot) -> Span

Examples found in repository?
examples/tokenizer.rs (line 115)
98    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
99        stream.try_parse(|stream| {
100            let snap = stream.snapshot();
101            let mut first_c = false;
102            let slice = stream.cur().advance_while(|c| {
103                if first_c {
104                    first_c = false;
105                    UnicodeXID::is_xid_start(c)
106                } else {
107                    UnicodeXID::is_xid_continue(c)
108                }
109            });
110            if slice.is_empty() {
111                Err("Expected identifier.")
112            } else {
113                Ok(Ident {
114                    string: String::from(slice),
115                    span: stream.since(snap),
116                })
117            }
118        })
119    }
Source

pub fn parse<P: Parse>(&mut self) -> Result<P>

Examples found in repository?
examples/tokenizer.rs (line 48)
47    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
48        stream.parse::<Quote>()?;
49
50        let inside = stream.try_parse(|stream| {
51            Ok(LitStr {
52                val: String::from(stream.cur().advance_while(|c| c != '\"')),
53            })
54        });
55
56        stream.parse::<Quote>()?;
57        inside
58    }
59}
60
61#[derive(Debug)]
62enum Literal {
63    Int(LitInt),
64    String(LitStr),
65}
66
67impl Parse for Literal {
68    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
69        if let Ok(lit_int) = stream.parse::<LitInt>() {
70            Ok(Literal::Int(lit_int))
71        } else if let Ok(lit_str) = stream.parse::<LitStr>() {
72            Ok(Literal::String(lit_str))
73        } else {
74            Err("Expected integer or str.")
75        }
76    }
77}
78
79simple_tok_spanned!(Quote, "\"");
80
81#[derive(Debug)]
82struct Ident {
83    string: String,
84    span: Span,
85}
86
87impl Spanned for Ident {
88    fn span(&self) -> Span {
89        self.span
90    }
91
92    fn span_ref_mut(&mut self) -> &mut Span {
93        &mut self.span
94    }
95}
96
97impl Parse for Ident {
98    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
99        stream.try_parse(|stream| {
100            let snap = stream.snapshot();
101            let mut first_c = false;
102            let slice = stream.cur().advance_while(|c| {
103                if first_c {
104                    first_c = false;
105                    UnicodeXID::is_xid_start(c)
106                } else {
107                    UnicodeXID::is_xid_continue(c)
108                }
109            });
110            if slice.is_empty() {
111                Err("Expected identifier.")
112            } else {
113                Ok(Ident {
114                    string: String::from(slice),
115                    span: stream.since(snap),
116                })
117            }
118        })
119    }
120}
121
122#[derive(Debug)]
123enum Symbol {
124    KwFunction,
125    KwLet,
126    KwIf,
127    Ident(Ident),
128}
129
130impl Parse for Symbol {
131    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
132        let ident: Ident = stream
133            .parse()
134            .map_err(|_e| "Expected identifier, `function`, `let` or `if`.")?;
135
136        Ok(match ident.string.as_str() {
137            "fun" => Symbol::KwFunction,
138            "let" => Symbol::KwLet,
139            "if" => Symbol::KwIf,
140            _ => Symbol::Ident(ident),
141        })
142    }
143}
144
145#[derive(Debug)]
146enum Punctuation {
147    Plus,
148    Minus,
149    Star,
150    Slash,
151}
152
153impl Parse for Punctuation {
154    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
155        stream.try_parse(|stream| {
156            Ok(
157                match stream
158                    .cur()
159                    .advance()
160                    .ok_or("Expected `+`, `-`, `*` or `/`.")?
161                {
162                    '+' => Punctuation::Plus,
163                    '-' => Punctuation::Minus,
164                    '*' => Punctuation::Star,
165                    '/' => Punctuation::Slash,
166                    _ => return Err("Expected `+`, `-`, `*` or `/`."),
167                },
168            )
169        })
170    }
171}
172
173// NOTE: A #[derive(Parse)] and #[derive(Spanned)] will probably be added in the future.
174#[derive(Debug)]
175enum Token {
176    Punctuation(Punctuation),
177    Literal(Literal),
178    Symbol(Symbol),
179}
180
181impl Parse for Token {
182    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
183        stream.skip_all(spec::is_whitespace);
184        if let Ok(lit) = stream.parse::<Literal>() {
185            Ok(Token::Literal(lit))
186        } else if let Ok(punctuation) = stream.parse::<Punctuation>() {
187            Ok(Token::Punctuation(punctuation))
188        } else if let Ok(symbol) = stream.parse::<Symbol>() {
189            Ok(Token::Symbol(symbol))
190        } else {
191            Err("Expected punctuation, symbol or literal.")
192        }
193    }
Source

pub fn cur(&mut self) -> &mut Cursor<'a>

Examples found in repository?
examples/tokenizer.rs (line 30)
13    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
14        fn to_u32(chars: &str) -> syntax_rs::Result<u32> {
15            if chars.len() == 0 {
16                return Err("Expected integer.");
17            }
18            let mut number = 0;
19
20            // We don't need to do .chars() here because we are only dealing with numbers.
21            for c in chars.as_bytes() {
22                let digit: u32 = *c as u32 - 0x30;
23                number *= 10;
24                number += digit;
25            }
26            Ok(number)
27        }
28
29        stream.try_parse(|stream| {
30            let negative = stream.cur().consume('-');
31            let mut value = to_u32(stream.cur().advance_while(|c| c.is_digit(10)))? as i64;
32            if negative {
33                value *= -1;
34            }
35
36            Ok(LitInt { value })
37        })
38    }
39}
40
41#[derive(Debug)]
42struct LitStr {
43    val: String,
44}
45
46impl Parse for LitStr {
47    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
48        stream.parse::<Quote>()?;
49
50        let inside = stream.try_parse(|stream| {
51            Ok(LitStr {
52                val: String::from(stream.cur().advance_while(|c| c != '\"')),
53            })
54        });
55
56        stream.parse::<Quote>()?;
57        inside
58    }
59}
60
61#[derive(Debug)]
62enum Literal {
63    Int(LitInt),
64    String(LitStr),
65}
66
67impl Parse for Literal {
68    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
69        if let Ok(lit_int) = stream.parse::<LitInt>() {
70            Ok(Literal::Int(lit_int))
71        } else if let Ok(lit_str) = stream.parse::<LitStr>() {
72            Ok(Literal::String(lit_str))
73        } else {
74            Err("Expected integer or str.")
75        }
76    }
77}
78
79simple_tok_spanned!(Quote, "\"");
80
81#[derive(Debug)]
82struct Ident {
83    string: String,
84    span: Span,
85}
86
87impl Spanned for Ident {
88    fn span(&self) -> Span {
89        self.span
90    }
91
92    fn span_ref_mut(&mut self) -> &mut Span {
93        &mut self.span
94    }
95}
96
97impl Parse for Ident {
98    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
99        stream.try_parse(|stream| {
100            let snap = stream.snapshot();
101            let mut first_c = false;
102            let slice = stream.cur().advance_while(|c| {
103                if first_c {
104                    first_c = false;
105                    UnicodeXID::is_xid_start(c)
106                } else {
107                    UnicodeXID::is_xid_continue(c)
108                }
109            });
110            if slice.is_empty() {
111                Err("Expected identifier.")
112            } else {
113                Ok(Ident {
114                    string: String::from(slice),
115                    span: stream.since(snap),
116                })
117            }
118        })
119    }
120}
121
122#[derive(Debug)]
123enum Symbol {
124    KwFunction,
125    KwLet,
126    KwIf,
127    Ident(Ident),
128}
129
130impl Parse for Symbol {
131    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
132        let ident: Ident = stream
133            .parse()
134            .map_err(|_e| "Expected identifier, `function`, `let` or `if`.")?;
135
136        Ok(match ident.string.as_str() {
137            "fun" => Symbol::KwFunction,
138            "let" => Symbol::KwLet,
139            "if" => Symbol::KwIf,
140            _ => Symbol::Ident(ident),
141        })
142    }
143}
144
145#[derive(Debug)]
146enum Punctuation {
147    Plus,
148    Minus,
149    Star,
150    Slash,
151}
152
153impl Parse for Punctuation {
154    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
155        stream.try_parse(|stream| {
156            Ok(
157                match stream
158                    .cur()
159                    .advance()
160                    .ok_or("Expected `+`, `-`, `*` or `/`.")?
161                {
162                    '+' => Punctuation::Plus,
163                    '-' => Punctuation::Minus,
164                    '*' => Punctuation::Star,
165                    '/' => Punctuation::Slash,
166                    _ => return Err("Expected `+`, `-`, `*` or `/`."),
167                },
168            )
169        })
170    }
Source

pub fn is_empty(&self) -> bool

Source

pub fn is_only_whitespaces(&self) -> bool

Source

pub fn skip_all(&mut self, pred: impl FnMut(char) -> bool) -> bool

Examples found in repository?
examples/tokenizer.rs (line 183)
182    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
183        stream.skip_all(spec::is_whitespace);
184        if let Ok(lit) = stream.parse::<Literal>() {
185            Ok(Token::Literal(lit))
186        } else if let Ok(punctuation) = stream.parse::<Punctuation>() {
187            Ok(Token::Punctuation(punctuation))
188        } else if let Ok(symbol) = stream.parse::<Symbol>() {
189            Ok(Token::Symbol(symbol))
190        } else {
191            Err("Expected punctuation, symbol or literal.")
192        }
193    }
Source

pub fn try_parse<R>( &mut self, parse_fn: impl FnOnce(&mut ParseStream<'a>) -> Result<R>, ) -> Result<R>

Tries to parse something using the parse_fn parameter. On failure; the cursor is reset to it’s original value.
NOTE: This function is generally much more expensive than just doing a simple check before parsing.

Examples found in repository?
examples/tokenizer.rs (lines 29-37)
13    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
14        fn to_u32(chars: &str) -> syntax_rs::Result<u32> {
15            if chars.len() == 0 {
16                return Err("Expected integer.");
17            }
18            let mut number = 0;
19
20            // We don't need to do .chars() here because we are only dealing with numbers.
21            for c in chars.as_bytes() {
22                let digit: u32 = *c as u32 - 0x30;
23                number *= 10;
24                number += digit;
25            }
26            Ok(number)
27        }
28
29        stream.try_parse(|stream| {
30            let negative = stream.cur().consume('-');
31            let mut value = to_u32(stream.cur().advance_while(|c| c.is_digit(10)))? as i64;
32            if negative {
33                value *= -1;
34            }
35
36            Ok(LitInt { value })
37        })
38    }
39}
40
41#[derive(Debug)]
42struct LitStr {
43    val: String,
44}
45
46impl Parse for LitStr {
47    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
48        stream.parse::<Quote>()?;
49
50        let inside = stream.try_parse(|stream| {
51            Ok(LitStr {
52                val: String::from(stream.cur().advance_while(|c| c != '\"')),
53            })
54        });
55
56        stream.parse::<Quote>()?;
57        inside
58    }
59}
60
61#[derive(Debug)]
62enum Literal {
63    Int(LitInt),
64    String(LitStr),
65}
66
67impl Parse for Literal {
68    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
69        if let Ok(lit_int) = stream.parse::<LitInt>() {
70            Ok(Literal::Int(lit_int))
71        } else if let Ok(lit_str) = stream.parse::<LitStr>() {
72            Ok(Literal::String(lit_str))
73        } else {
74            Err("Expected integer or str.")
75        }
76    }
77}
78
79simple_tok_spanned!(Quote, "\"");
80
81#[derive(Debug)]
82struct Ident {
83    string: String,
84    span: Span,
85}
86
87impl Spanned for Ident {
88    fn span(&self) -> Span {
89        self.span
90    }
91
92    fn span_ref_mut(&mut self) -> &mut Span {
93        &mut self.span
94    }
95}
96
97impl Parse for Ident {
98    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
99        stream.try_parse(|stream| {
100            let snap = stream.snapshot();
101            let mut first_c = false;
102            let slice = stream.cur().advance_while(|c| {
103                if first_c {
104                    first_c = false;
105                    UnicodeXID::is_xid_start(c)
106                } else {
107                    UnicodeXID::is_xid_continue(c)
108                }
109            });
110            if slice.is_empty() {
111                Err("Expected identifier.")
112            } else {
113                Ok(Ident {
114                    string: String::from(slice),
115                    span: stream.since(snap),
116                })
117            }
118        })
119    }
120}
121
122#[derive(Debug)]
123enum Symbol {
124    KwFunction,
125    KwLet,
126    KwIf,
127    Ident(Ident),
128}
129
130impl Parse for Symbol {
131    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
132        let ident: Ident = stream
133            .parse()
134            .map_err(|_e| "Expected identifier, `function`, `let` or `if`.")?;
135
136        Ok(match ident.string.as_str() {
137            "fun" => Symbol::KwFunction,
138            "let" => Symbol::KwLet,
139            "if" => Symbol::KwIf,
140            _ => Symbol::Ident(ident),
141        })
142    }
143}
144
145#[derive(Debug)]
146enum Punctuation {
147    Plus,
148    Minus,
149    Star,
150    Slash,
151}
152
153impl Parse for Punctuation {
154    fn parse(stream: &mut ParseStream) -> syntax_rs::Result<Self> {
155        stream.try_parse(|stream| {
156            Ok(
157                match stream
158                    .cur()
159                    .advance()
160                    .ok_or("Expected `+`, `-`, `*` or `/`.")?
161                {
162                    '+' => Punctuation::Plus,
163                    '-' => Punctuation::Minus,
164                    '*' => Punctuation::Star,
165                    '/' => Punctuation::Slash,
166                    _ => return Err("Expected `+`, `-`, `*` or `/`."),
167                },
168            )
169        })
170    }

Auto Trait Implementations§

§

impl<'a> Freeze for ParseStream<'a>

§

impl<'a> RefUnwindSafe for ParseStream<'a>

§

impl<'a> Send for ParseStream<'a>

§

impl<'a> Sync for ParseStream<'a>

§

impl<'a> Unpin for ParseStream<'a>

§

impl<'a> UnwindSafe for ParseStream<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.