Option
tp::Option<T> and tp::Exists<T> are types used to represent optional syntax trees.
tp::Option<T> stores the syntax tree itself, and tp::Exists<T> stores a boolean value to test if the syntax tree is present.
Production
Option<T> => ε | T
Example
Ident is a terminal struct not shown here
#![allow(unused)] fn main() { use teleparse::prelude::*; #[derive_syntax] #[teleparse(root)] #[derive(Debug, PartialEq)] struct OptIdent(tp::Option<Ident>); #[test] fn test_none() -> Result<(), GrammarError> { let t = OptIdent::parse("+")?.unwrap(); assert_eq!(t, OptIdent(Node::new(0..0, None).into())); Ok(()) } #[test] fn test_some() -> Result<(), GrammarError> { let t = OptIdent::parse("a")?.unwrap(); assert_eq!(t, OptIdent(Node::new(0..1, Some(Ident::from_span(0..1)).into())); Ok(()) } }
Deref
tp::Option<T> / tp::Exists<T> implements Deref and DerefMut. So you can
use them as &std::option::Option<T> / &bool.
#![allow(unused)] fn main() { let t = OptIdent::parse("a")?.unwrap(); assert!(t.0.is_some()); }
Parsing
There are 3 possible outcomes when parsing an Option<T>:
- The next token is not in FIRST(T). The parser will return
None. - The next token is in FIRST(T):
- If the parser can parse
T, it will returnSome(T). - If the parser cannot parse
T, it will record an error, returnNone, and continue.
- If the parser can parse
In any case, the parser will not panic.
Common LL(1) Violations
Option<Option<T>>- sinceSome(None)andNoneare indistinguishable.(Option<T>, T)- since (None, T) and (Some(T), …) are indistinguishable.