|
|
@ -6,14 +6,19 @@ use std::{
|
|
|
|
sync::atomic::AtomicUsize,
|
|
|
|
sync::atomic::AtomicUsize,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The contents of a node in our parse tree. The parse tree consists of both terminal and
|
|
|
|
|
|
|
|
/// nonterminal symbols.
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
pub enum Value {
|
|
|
|
pub enum Value {
|
|
|
|
/// The start symbol of our parse tree. Each parse tree is rooted in a node whose value is the
|
|
|
|
/// The start symbol of our parse tree. Each parse tree is rooted in a node whose value is the
|
|
|
|
/// start symbol. This is the only node in the tree that should utilize the start symbol.
|
|
|
|
/// start symbol. This is the only node in the tree that should utilize the start symbol.
|
|
|
|
Start,
|
|
|
|
Start,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// The children of a statement symbol make up the components of what will become a statement
|
|
|
|
|
|
|
|
/// in our ast
|
|
|
|
Statement,
|
|
|
|
Statement,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Each of the tokens from the lex stage becomes a terminal node on our tree
|
|
|
|
Terminal(Token),
|
|
|
|
Terminal(Token),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -43,19 +48,28 @@ pub struct Node {
|
|
|
|
|
|
|
|
|
|
|
|
impl Node {
|
|
|
|
impl Node {
|
|
|
|
fn new() -> Cursor {
|
|
|
|
fn new() -> Cursor {
|
|
|
|
let root = Node {
|
|
|
|
let root = Rc::new(Node {
|
|
|
|
id: next_id(),
|
|
|
|
id: next_id(),
|
|
|
|
parent: None,
|
|
|
|
parent: None,
|
|
|
|
value: Value::Start,
|
|
|
|
value: Value::Start,
|
|
|
|
children: RefCell::new(Vec::new()),
|
|
|
|
children: RefCell::new(Vec::new()),
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
let root = Rc::new(root);
|
|
|
|
|
|
|
|
Cursor {
|
|
|
|
Cursor {
|
|
|
|
target: Rc::clone(&root),
|
|
|
|
target: Rc::clone(&root),
|
|
|
|
|
|
|
|
prev: root.id,
|
|
|
|
root,
|
|
|
|
root,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn is_semi(&self) -> bool {
|
|
|
|
|
|
|
|
matches!(self.value, Value::Terminal(Token::Semi(_)))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl PartialEq for Node {
|
|
|
|
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
|
|
|
|
self.id == other.id
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct ChildIter {
|
|
|
|
pub struct ChildIter {
|
|
|
@ -74,6 +88,7 @@ impl Iterator for ChildIter {
|
|
|
|
Some(Cursor {
|
|
|
|
Some(Cursor {
|
|
|
|
target: Rc::clone(v),
|
|
|
|
target: Rc::clone(v),
|
|
|
|
root: Rc::clone(&self.root),
|
|
|
|
root: Rc::clone(&self.root),
|
|
|
|
|
|
|
|
prev: self.target.id,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -83,11 +98,15 @@ fn next_id() -> usize {
|
|
|
|
LAST_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
|
|
|
|
LAST_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Cursor values expose access to a parse tree.
|
|
|
|
/// Cursor values expose access to a parse tree. A cursor is logically a pointer to a single node
|
|
|
|
|
|
|
|
/// within a parse tree. The cursor helps with the ownership structure: so long as there is a
|
|
|
|
|
|
|
|
/// cursor to any node on the tree, the tree remains in memory. Once there are no cursors pointed
|
|
|
|
|
|
|
|
/// at the tree, it is dropped.
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Cursor {
|
|
|
|
pub struct Cursor {
|
|
|
|
pub target: Rc<Node>,
|
|
|
|
pub target: Rc<Node>,
|
|
|
|
root: Rc<Node>,
|
|
|
|
root: Rc<Node>,
|
|
|
|
|
|
|
|
prev: usize,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Cursor {
|
|
|
|
impl Cursor {
|
|
|
@ -99,7 +118,7 @@ impl Cursor {
|
|
|
|
None => Err(ParseError::AtRootAlready),
|
|
|
|
None => Err(ParseError::AtRootAlready),
|
|
|
|
Some(parent) => match parent.upgrade() {
|
|
|
|
Some(parent) => match parent.upgrade() {
|
|
|
|
Some(parent) => {
|
|
|
|
Some(parent) => {
|
|
|
|
self.target = parent;
|
|
|
|
self.goto(parent);
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => Err(ParseError::ParentIsGone),
|
|
|
|
None => Err(ParseError::ParentIsGone),
|
|
|
@ -107,6 +126,40 @@ impl Cursor {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// moves the cursor horizontally in the tree, selecting the node that appears after the
|
|
|
|
|
|
|
|
/// current target node
|
|
|
|
|
|
|
|
pub fn next_sibling(&mut self) -> Result<bool, ParseError> {
|
|
|
|
|
|
|
|
let next = match self.pick_next_sibling()? {
|
|
|
|
|
|
|
|
Some(node) => node,
|
|
|
|
|
|
|
|
None => return Ok(false),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
self.prev = self.target.id;
|
|
|
|
|
|
|
|
self.target = next;
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn pick_next_sibling(&mut self) -> Result<Option<Rc<Node>>, ParseError> {
|
|
|
|
|
|
|
|
let parent = self
|
|
|
|
|
|
|
|
.target
|
|
|
|
|
|
|
|
.parent
|
|
|
|
|
|
|
|
.clone()
|
|
|
|
|
|
|
|
.ok_or_else(|| ParseError::AtRootAlready)?;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SAFETY: this is ok because the cursor always retains a pointer to the root of the tree,
|
|
|
|
|
|
|
|
// so we know that since we have a cursor, the parent cannot yet be dropped
|
|
|
|
|
|
|
|
let parent = parent.upgrade().unwrap();
|
|
|
|
|
|
|
|
let mut found_self = false;
|
|
|
|
|
|
|
|
for child in parent.children.borrow().iter() {
|
|
|
|
|
|
|
|
if found_self {
|
|
|
|
|
|
|
|
return Ok(Some(child.clone()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if child.id == self.target.id {
|
|
|
|
|
|
|
|
found_self = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(None)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Adds a value to the children of the current target node, then descends to select that
|
|
|
|
/// Adds a value to the children of the current target node, then descends to select that
|
|
|
|
/// child.
|
|
|
|
/// child.
|
|
|
|
fn push(&mut self, v: Value) -> Result<(), ParseError> {
|
|
|
|
fn push(&mut self, v: Value) -> Result<(), ParseError> {
|
|
|
@ -124,12 +177,12 @@ impl Cursor {
|
|
|
|
.children
|
|
|
|
.children
|
|
|
|
.try_borrow_mut()?
|
|
|
|
.try_borrow_mut()?
|
|
|
|
.push(Rc::clone(&node));
|
|
|
|
.push(Rc::clone(&node));
|
|
|
|
self.target = node;
|
|
|
|
self.goto(node);
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn up_to_root(&mut self) {
|
|
|
|
pub fn up_to_root(&mut self) {
|
|
|
|
self.target = Rc::clone(&self.root);
|
|
|
|
self.goto(Rc::clone(&self.root));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn value(&self) -> &Value {
|
|
|
|
pub fn value(&self) -> &Value {
|
|
|
@ -154,35 +207,33 @@ impl Cursor {
|
|
|
|
Rc::clone(&self.root)
|
|
|
|
Rc::clone(&self.root)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// pub fn render_textree<W: Write>(&self, w: &mut W, depth: u32) {
|
|
|
|
fn goto(&mut self, next: Rc<Node>) {
|
|
|
|
// write!(w, "{:?} {pad:?}", self.target.value, pad = depth * 2);
|
|
|
|
self.prev = self.target.id;
|
|
|
|
// for child in self.iter_children() {
|
|
|
|
self.target = next;
|
|
|
|
// child.render_textree(w, depth + 1);
|
|
|
|
}
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub struct Parser<'text> {
|
|
|
|
pub struct Parser<'text> {
|
|
|
|
source: Lexer<'text>,
|
|
|
|
input: Lexer<'text>,
|
|
|
|
cursor: Cursor,
|
|
|
|
output: Cursor,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<'text> Parser<'text> {
|
|
|
|
impl<'text> Parser<'text> {
|
|
|
|
pub fn new(source: Lexer<'text>) -> Self {
|
|
|
|
pub fn new(source: Lexer<'text>) -> Self {
|
|
|
|
Self {
|
|
|
|
Self {
|
|
|
|
source,
|
|
|
|
input: source,
|
|
|
|
cursor: Node::new(),
|
|
|
|
output: Node::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn parse(mut self) -> Result<Cursor, ParseError> {
|
|
|
|
pub fn parse(mut self) -> Result<Cursor, ParseError> {
|
|
|
|
while self.step()? {}
|
|
|
|
while self.step()? {}
|
|
|
|
self.cursor.up_to_root();
|
|
|
|
self.output.up_to_root();
|
|
|
|
Ok(self.cursor)
|
|
|
|
Ok(self.output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn step(&mut self) -> Result<bool, ParseError> {
|
|
|
|
fn step(&mut self) -> Result<bool, ParseError> {
|
|
|
|
match self.cursor.value() {
|
|
|
|
match self.output.value() {
|
|
|
|
Value::Start => self.step_start(),
|
|
|
|
Value::Start => self.step_start(),
|
|
|
|
Value::Statement => self.step_statement(),
|
|
|
|
Value::Statement => self.step_statement(),
|
|
|
|
Value::Terminal(_) => panic!(),
|
|
|
|
Value::Terminal(_) => panic!(),
|
|
|
@ -190,30 +241,45 @@ impl<'text> Parser<'text> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn step_start(&mut self) -> Result<bool, ParseError> {
|
|
|
|
fn step_start(&mut self) -> Result<bool, ParseError> {
|
|
|
|
assert!(matches!(self.cursor.value(), Value::Start));
|
|
|
|
assert!(matches!(self.output.value(), Value::Start));
|
|
|
|
match self.source.peek()? {
|
|
|
|
match self.input.peek()? {
|
|
|
|
Some(Token::Word(_)) => {
|
|
|
|
Some(Token::Word(_)) => {
|
|
|
|
self.cursor.push(Value::Statement)?;
|
|
|
|
self.output.push(Value::Statement)?;
|
|
|
|
let token = self.source.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
self.cursor.push(Value::Terminal(token))?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.cursor.up()?;
|
|
|
|
self.output.up()?;
|
|
|
|
Ok(true)
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(Token::Glob(_)) => {
|
|
|
|
Some(Token::Glob(_)) => {
|
|
|
|
let token = self.source.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
Err(ParseError::UnexpectedToken(token))
|
|
|
|
Err(ParseError::UnexpectedToken(token))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(Token::Semi(_)) => {
|
|
|
|
|
|
|
|
self.output.push(Value::Statement)?;
|
|
|
|
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
|
|
|
|
self.output.up()?;
|
|
|
|
|
|
|
|
self.output.up()?;
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
|
|
|
|
}
|
|
|
|
None => Ok(false),
|
|
|
|
None => Ok(false),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn step_statement(&mut self) -> Result<bool, ParseError> {
|
|
|
|
fn step_statement(&mut self) -> Result<bool, ParseError> {
|
|
|
|
assert!(matches!(self.cursor.value(), Value::Statement));
|
|
|
|
assert!(matches!(self.output.value(), Value::Statement));
|
|
|
|
match self.source.peek()? {
|
|
|
|
match self.input.peek()? {
|
|
|
|
Some(Token::Word(_) | Token::Glob(_)) => {
|
|
|
|
Some(Token::Word(_) | Token::Glob(_)) => {
|
|
|
|
let token = self.source.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
self.cursor.push(Value::Terminal(token))?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.cursor.up()?;
|
|
|
|
self.output.up()?;
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(Token::Semi(_)) => {
|
|
|
|
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
|
|
|
|
self.output.up()?;
|
|
|
|
|
|
|
|
self.output.up()?;
|
|
|
|
Ok(true)
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => Ok(false),
|
|
|
|
None => Ok(false),
|
|
|
|