67 lines
1.6 KiB
Rust
67 lines
1.6 KiB
Rust
|
// <binding_pattern> ::= Symbol { <tight_binding_pattern> }
|
||
|
// <tight_binding_pattern> ::= Literal
|
||
|
// | Symbol
|
||
|
// | OpenParen <binding_pattern> CloseParen
|
||
|
|
||
|
use std::mem::{discriminant, Discriminant};
|
||
|
|
||
|
use crate::token::{Literal, Token};
|
||
|
|
||
|
use super::{Parsable, ParseError, WrappedLexer, absorb_token_or_error};
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum TightBindingPattern {
|
||
|
Literal(Literal),
|
||
|
Symbol(String),
|
||
|
Group(BindingPattern),
|
||
|
}
|
||
|
|
||
|
impl Parsable for TightBindingPattern {
|
||
|
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||
|
(
|
||
|
vec![
|
||
|
discriminant(&Token::Literal(Literal::Int(0))),
|
||
|
discriminant(&Token::Symbol(String::new())),
|
||
|
discriminant(&Token::OpenParen),
|
||
|
],
|
||
|
false,
|
||
|
)
|
||
|
}
|
||
|
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||
|
let location = l.span();
|
||
|
match l.curtok() {
|
||
|
Token::Literal(l) => Ok(TightBindingPattern::Literal(l.clone())),
|
||
|
Token::Symbol(name) => Ok(TightBindingPattern::Symbol(name.to_owned())),
|
||
|
Token::OpenParen => {
|
||
|
let patt = BindingPattern::parse(l)?;
|
||
|
absorb_token_or_error(l, discriminant(&Token::CloseParen))?;
|
||
|
Ok(TightBindingPattern::Group(patt))
|
||
|
},
|
||
|
_ => {
|
||
|
Err(ParseError {
|
||
|
expected: Self::expected().0,
|
||
|
location,
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct BindingPattern(String, Vec<TightBindingPattern>);
|
||
|
|
||
|
impl Parsable for BindingPattern {
|
||
|
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||
|
(
|
||
|
vec![
|
||
|
discriminant(&Token::Symbol(String::new())),
|
||
|
], false
|
||
|
)
|
||
|
}
|
||
|
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||
|
let name = String::parse(l)?;
|
||
|
let fields = Vec::parse(l)?;
|
||
|
Ok(Self(name, fields))
|
||
|
}
|
||
|
}
|