Move parsing of field pattern lists to the parser (where it belongs)
This commit is contained in:
parent
d2769837f1
commit
f9a6050034
6 changed files with 71 additions and 64 deletions
|
@ -857,11 +857,19 @@ impl ExprCollector {
|
|||
let fields = p
|
||||
.field_pat_list()
|
||||
.expect("every struct should have a field list")
|
||||
.field_pats()
|
||||
.into_iter()
|
||||
.pats()
|
||||
.map(|f| {
|
||||
let name = Name::new(f.ident);
|
||||
let pat = self.collect_pat(&*f.pat);
|
||||
let ast_pat = f.pat().expect("field pat always contains a pattern");
|
||||
let pat = self.collect_pat(ast_pat);
|
||||
let name = f
|
||||
.name()
|
||||
.unwrap_or_else(|| {
|
||||
ast::BindPat::cast(ast_pat.syntax())
|
||||
.expect("field pat without label is a bind pat")
|
||||
.name()
|
||||
.expect("bind pat has a name")
|
||||
})
|
||||
.as_name();
|
||||
FieldPat { name, pat }
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -664,55 +664,6 @@ impl LiteralExpr {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct FieldPat {
|
||||
pub ident: SmolStr,
|
||||
// FIXME: could we use a regular reference?
|
||||
pub pat: TreeArc<Pat>,
|
||||
}
|
||||
|
||||
impl FieldPatList {
|
||||
// TODO: try returning an iterator?
|
||||
// FIXME: shouldnt the parser do this? :o
|
||||
pub fn field_pats(&self) -> Vec<FieldPat> {
|
||||
let mut child_iter = self.syntax().children();
|
||||
let mut pats = Vec::new();
|
||||
|
||||
while let Some(node) = child_iter.next() {
|
||||
let kind = node.kind();
|
||||
if kind != IDENT && kind != BIND_PAT {
|
||||
continue;
|
||||
}
|
||||
|
||||
let ident = if let Some(text) = node.leaf_text() {
|
||||
text.clone()
|
||||
} else {
|
||||
SmolStr::new(node.text().to_string())
|
||||
};
|
||||
let mut pat = Pat::cast(node).map(AstNode::to_owned);
|
||||
|
||||
// get pat
|
||||
while let Some(node) = child_iter.next() {
|
||||
if node.kind() == COMMA {
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some(p) = Pat::cast(node) {
|
||||
pat = Some(p.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let field_pat = FieldPat {
|
||||
ident: ident,
|
||||
pat: pat.unwrap(),
|
||||
};
|
||||
pats.push(field_pat);
|
||||
}
|
||||
|
||||
pats
|
||||
}
|
||||
}
|
||||
|
||||
impl BindPat {
|
||||
pub fn is_mutable(&self) -> bool {
|
||||
self.syntax().children().any(|n| n.kind() == MUT_KW)
|
||||
|
|
|
@ -858,6 +858,35 @@ impl FieldExpr {
|
|||
}
|
||||
}
|
||||
|
||||
// FieldPat
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct FieldPat {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
unsafe impl TransparentNewType for FieldPat {
|
||||
type Repr = rowan::SyntaxNode<RaTypes>;
|
||||
}
|
||||
|
||||
impl AstNode for FieldPat {
|
||||
fn cast(syntax: &SyntaxNode) -> Option<&Self> {
|
||||
match syntax.kind() {
|
||||
FIELD_PAT => Some(FieldPat::from_repr(syntax.into_repr())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
fn to_owned(&self) -> TreeArc<FieldPat> { TreeArc::cast(self.syntax.to_owned()) }
|
||||
}
|
||||
|
||||
|
||||
impl ast::NameOwner for FieldPat {}
|
||||
impl FieldPat {
|
||||
pub fn pat(&self) -> Option<&Pat> {
|
||||
super::child_opt(self)
|
||||
}
|
||||
}
|
||||
|
||||
// FieldPatList
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
|
@ -880,7 +909,11 @@ impl AstNode for FieldPatList {
|
|||
}
|
||||
|
||||
|
||||
impl FieldPatList {}
|
||||
impl FieldPatList {
|
||||
pub fn pats(&self) -> impl Iterator<Item = &FieldPat> {
|
||||
super::children(self)
|
||||
}
|
||||
}
|
||||
|
||||
// FloatNumber
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
|
|
@ -154,6 +154,7 @@ Grammar(
|
|||
"PATH_PAT",
|
||||
"STRUCT_PAT",
|
||||
"FIELD_PAT_LIST",
|
||||
"FIELD_PAT",
|
||||
"TUPLE_STRUCT_PAT",
|
||||
"TUPLE_PAT",
|
||||
"SLICE_PAT",
|
||||
|
@ -495,7 +496,11 @@ Grammar(
|
|||
"PlaceholderPat": (),
|
||||
"PathPat": ( options: [ "Path" ] ),
|
||||
"StructPat": ( options: ["FieldPatList", "Path"] ),
|
||||
"FieldPatList": (),
|
||||
"FieldPatList": ( collections: [["pats", "FieldPat"]] ),
|
||||
"FieldPat": (
|
||||
traits: ["NameOwner"],
|
||||
options: ["Pat"]
|
||||
),
|
||||
"TupleStructPat": (
|
||||
options: ["Path"],
|
||||
collections: [["args", "Pat"]],
|
||||
|
|
|
@ -128,15 +128,7 @@ fn field_pat_list(p: &mut Parser) {
|
|||
while !p.at(EOF) && !p.at(R_CURLY) {
|
||||
match p.current() {
|
||||
DOTDOT => p.bump(),
|
||||
IDENT if p.nth(1) == COLON => {
|
||||
p.bump();
|
||||
p.bump();
|
||||
pattern(p);
|
||||
}
|
||||
L_CURLY => error_block(p, "expected ident"),
|
||||
_ => {
|
||||
bind_pat(p, false);
|
||||
}
|
||||
_ => field_pat(p),
|
||||
}
|
||||
if !p.at(R_CURLY) {
|
||||
p.expect(COMMA);
|
||||
|
@ -146,6 +138,22 @@ fn field_pat_list(p: &mut Parser) {
|
|||
m.complete(p, FIELD_PAT_LIST);
|
||||
}
|
||||
|
||||
fn field_pat(p: &mut Parser) {
|
||||
let m = p.start();
|
||||
match p.current() {
|
||||
IDENT if p.nth(1) == COLON => {
|
||||
name(p);
|
||||
p.bump();
|
||||
pattern(p);
|
||||
}
|
||||
L_CURLY => error_block(p, "expected ident"),
|
||||
_ => {
|
||||
bind_pat(p, false);
|
||||
}
|
||||
}
|
||||
m.complete(p, FIELD_PAT);
|
||||
}
|
||||
|
||||
// test placeholder_pat
|
||||
// fn main() { let _ = (); }
|
||||
fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
|
||||
|
|
|
@ -152,6 +152,7 @@ pub enum SyntaxKind {
|
|||
PATH_PAT,
|
||||
STRUCT_PAT,
|
||||
FIELD_PAT_LIST,
|
||||
FIELD_PAT,
|
||||
TUPLE_STRUCT_PAT,
|
||||
TUPLE_PAT,
|
||||
SLICE_PAT,
|
||||
|
@ -414,6 +415,7 @@ impl SyntaxKind {
|
|||
PATH_PAT => &SyntaxInfo { name: "PATH_PAT" },
|
||||
STRUCT_PAT => &SyntaxInfo { name: "STRUCT_PAT" },
|
||||
FIELD_PAT_LIST => &SyntaxInfo { name: "FIELD_PAT_LIST" },
|
||||
FIELD_PAT => &SyntaxInfo { name: "FIELD_PAT" },
|
||||
TUPLE_STRUCT_PAT => &SyntaxInfo { name: "TUPLE_STRUCT_PAT" },
|
||||
TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
|
||||
SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
|
||||
|
|
Loading…
Add table
Reference in a new issue