Replace contract_child to a less ad-hoc API

This commit is contained in:
pcpthm 2019-03-19 18:44:23 +09:00
parent e2ed813e89
commit 4cf179c089
2 changed files with 37 additions and 40 deletions

View File

@ -82,16 +82,15 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
}; };
let (cm, blocklike) = expr_stmt(p); let (cm, blocklike) = expr_stmt(p);
let kind = cm.as_ref().map(|cm| cm.kind()).unwrap_or(ERROR);
if let Some(cm) = &cm { if has_attrs && !is_expr_stmt_attr_allowed(kind) {
if has_attrs && !is_expr_stmt_attr_allowed(cm.kind()) { // test_err attr_on_expr_not_allowed
// test_err attr_on_expr_not_allowed // fn foo() {
// fn foo() { // #[A] 1 + 2;
// #[A] 1 + 2; // #[B] if true {};
// #[B] if true {}; // }
// } p.error(format!("attributes are not allowed on {:?}", kind));
p.error(format!("attributes are not allowed on {:?}", cm.kind()));
}
} }
if p.at(R_CURLY) { if p.at(R_CURLY) {
@ -101,7 +100,8 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
// #[B] &() // #[B] &()
// } // }
if let Some(cm) = cm { if let Some(cm) = cm {
m.contract_child(p, cm); cm.undo_completion(p).abandon(p);
m.complete(p, kind);
} else { } else {
m.abandon(p); m.abandon(p);
} }

View File

@ -212,8 +212,9 @@ impl Marker {
} }
_ => unreachable!(), _ => unreachable!(),
} }
let finish_pos = p.events.len() as u32;
p.push_event(Event::Finish); p.push_event(Event::Finish);
CompletedMarker::new(self.pos, kind) CompletedMarker::new(self.pos, finish_pos, kind)
} }
/// Abandons the syntax tree node. All its children /// Abandons the syntax tree node. All its children
@ -228,36 +229,17 @@ impl Marker {
} }
} }
} }
/// Contract a node `cm` and complete as `cm`'s `kind`.
/// `cm` must be a child of `m` to work correctly.
/// ```text
/// m--A m--A
/// +--cm--B -> +--B
/// +--C C
///
/// [m: TOMBSTONE, A, cm: Start(k), B, Finish, C]
/// [m: Start(k), A, cm: TOMBSTONE, B, Finish, C]
/// ```
pub(crate) fn contract_child(mut self, p: &mut Parser, cm: CompletedMarker) -> CompletedMarker {
self.bomb.defuse();
match p.events[self.pos as usize] {
Event::Start { kind: ref mut slot, .. } => *slot = cm.kind(),
_ => unreachable!(),
};
match p.events[cm.0 as usize] {
Event::Start { kind: ref mut slot, .. } => *slot = TOMBSTONE,
_ => unreachable!(),
};
CompletedMarker::new(self.pos, cm.kind())
}
} }
pub(crate) struct CompletedMarker(u32, SyntaxKind); pub(crate) struct CompletedMarker {
start_pos: u32,
finish_pos: u32,
kind: SyntaxKind,
}
impl CompletedMarker { impl CompletedMarker {
fn new(pos: u32, kind: SyntaxKind) -> Self { fn new(start_pos: u32, finish_pos: u32, kind: SyntaxKind) -> Self {
CompletedMarker(pos, kind) CompletedMarker { start_pos, finish_pos, kind }
} }
/// This method allows to create a new node which starts /// This method allows to create a new node which starts
@ -274,17 +256,32 @@ impl CompletedMarker {
/// distance to `NEWSTART` into forward_parent(=2 in this case); /// distance to `NEWSTART` into forward_parent(=2 in this case);
pub(crate) fn precede(self, p: &mut Parser) -> Marker { pub(crate) fn precede(self, p: &mut Parser) -> Marker {
let new_pos = p.start(); let new_pos = p.start();
let idx = self.0 as usize; let idx = self.start_pos as usize;
match p.events[idx] { match p.events[idx] {
Event::Start { ref mut forward_parent, .. } => { Event::Start { ref mut forward_parent, .. } => {
*forward_parent = Some(new_pos.pos - self.0); *forward_parent = Some(new_pos.pos - self.start_pos);
} }
_ => unreachable!(), _ => unreachable!(),
} }
new_pos new_pos
} }
/// Undo this completion and turns into a `Marker`
pub(crate) fn undo_completion(self, p: &mut Parser) -> Marker {
let start_idx = self.start_pos as usize;
let finish_idx = self.finish_pos as usize;
match p.events[start_idx] {
Event::Start { ref mut kind, forward_parent: None } => *kind = TOMBSTONE,
_ => unreachable!(),
}
match p.events[finish_idx] {
ref mut slot @ Event::Finish => *slot = Event::tombstone(),
_ => unreachable!(),
}
Marker::new(self.start_pos)
}
pub(crate) fn kind(&self) -> SyntaxKind { pub(crate) fn kind(&self) -> SyntaxKind {
self.1 self.kind
} }
} }