Move parsing of field pattern lists to the parser (where it belongs)

This commit is contained in:
Marcus Klaas de Vries 2019-01-18 14:52:31 +01:00 committed by Aleksey Kladov
parent d2769837f1
commit f9a6050034
6 changed files with 71 additions and 64 deletions

View file

@ -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();

View file

@ -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)

View file

@ -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)]

View file

@ -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"]],

View file

@ -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 {

View file

@ -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" },