Starting to iterate through the token tree.
This commit is contained in:
parent
371d74e691
commit
4b9e84375e
@ -32,6 +32,6 @@ async fn _parse_org_mode(
|
|||||||
body: String,
|
body: String,
|
||||||
) -> Result<(StatusCode, Json<OwnerTree>), Box<dyn std::error::Error>> {
|
) -> Result<(StatusCode, Json<OwnerTree>), Box<dyn std::error::Error>> {
|
||||||
let ast = emacs_parse_org_document(&body).await?;
|
let ast = emacs_parse_org_document(&body).await?;
|
||||||
let owner_tree = build_owner_tree(body.as_str()).map_err(|e| e.to_string())?;
|
let owner_tree = build_owner_tree(body.as_str(), ast.as_str()).map_err(|e| e.to_string())?;
|
||||||
Ok((StatusCode::OK, Json(owner_tree)))
|
Ok((StatusCode::OK, Json(owner_tree)))
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,122 @@
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::sexp::sexp_with_padding;
|
use crate::sexp::{sexp_with_padding, Token};
|
||||||
|
|
||||||
pub fn build_owner_tree(file_contents: &str) -> Result<OwnerTree, Box<dyn std::error::Error + '_>> {
|
pub fn build_owner_tree<'a>(
|
||||||
let (_remaining, parsed_sexp) = sexp_with_padding(file_contents)?;
|
body: &'a str,
|
||||||
|
ast_raw: &'a str,
|
||||||
|
) -> Result<OwnerTree, Box<dyn std::error::Error + 'a>> {
|
||||||
|
let (_remaining, parsed_sexp) = sexp_with_padding(ast_raw)?;
|
||||||
|
let lists = find_lists_in_document(&parsed_sexp)?;
|
||||||
|
|
||||||
Ok(OwnerTree {})
|
Ok(OwnerTree {
|
||||||
|
ast: ast_raw.to_owned(),
|
||||||
|
children: lists,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct OwnerTree {}
|
pub struct OwnerTree {
|
||||||
|
ast: String,
|
||||||
|
children: Vec<PlainList>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct PlainList {
|
||||||
|
position: SourceRange,
|
||||||
|
children: Vec<PlainListItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct PlainListItem {
|
||||||
|
position: SourceRange,
|
||||||
|
children: Vec<PlainListItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct SourceRange {
|
||||||
|
start_line: u32,
|
||||||
|
end_line: u32, // Exclusive
|
||||||
|
start_character: u32,
|
||||||
|
end_character: u32, // Exclusive
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_lists_in_document<'a>(
|
||||||
|
current_token: &Token<'a>,
|
||||||
|
) -> Result<Vec<PlainList>, Box<dyn std::error::Error>> {
|
||||||
|
// DFS looking for top-level lists
|
||||||
|
|
||||||
|
let mut found_lists = Vec::new();
|
||||||
|
let children = current_token.as_list()?;
|
||||||
|
let token_name = "org-data";
|
||||||
|
assert_name(current_token, token_name)?;
|
||||||
|
|
||||||
|
// skip 2 to skip token name and standard properties
|
||||||
|
for child_token in children.iter().skip(2) {
|
||||||
|
found_lists.extend(recurse_token(child_token)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(found_lists)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_name<'s>(emacs: &'s Token<'s>, name: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let children = emacs.as_list()?;
|
||||||
|
let first_child = children
|
||||||
|
.first()
|
||||||
|
.ok_or("Should have at least one child.")?
|
||||||
|
.as_atom()?;
|
||||||
|
if first_child != name {
|
||||||
|
Err(format!(
|
||||||
|
"Expected a {expected} cell, but found a {found} cell.",
|
||||||
|
expected = name,
|
||||||
|
found = first_child
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recurse_token<'a>(
|
||||||
|
current_token: &Token<'a>,
|
||||||
|
) -> Result<Vec<PlainList>, Box<dyn std::error::Error>> {
|
||||||
|
match current_token {
|
||||||
|
Token::Atom(_) | Token::TextWithProperties(_) => Ok(Vec::new()),
|
||||||
|
Token::List(_) => {
|
||||||
|
let new_lists = find_lists_in_list(current_token)?;
|
||||||
|
Ok(new_lists)
|
||||||
|
}
|
||||||
|
Token::Vector(_) => {
|
||||||
|
let new_lists = find_lists_in_vector(current_token)?;
|
||||||
|
Ok(new_lists)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_lists_in_list<'a>(
|
||||||
|
current_token: &Token<'a>,
|
||||||
|
) -> Result<Vec<PlainList>, Box<dyn std::error::Error>> {
|
||||||
|
let mut found_lists = Vec::new();
|
||||||
|
let children = current_token.as_list()?;
|
||||||
|
if assert_name(current_token, "plain-list").is_ok() {
|
||||||
|
// Found a list!
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip 2 to skip token name and standard properties
|
||||||
|
for child_token in children.iter().skip(2) {
|
||||||
|
found_lists.extend(recurse_token(child_token)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(found_lists)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_lists_in_vector<'a>(
|
||||||
|
current_token: &Token<'a>,
|
||||||
|
) -> Result<Vec<PlainList>, Box<dyn std::error::Error>> {
|
||||||
|
let mut found_lists = Vec::new();
|
||||||
|
let children = current_token.as_vector()?;
|
||||||
|
|
||||||
|
for child_token in children.iter() {
|
||||||
|
found_lists.extend(recurse_token(child_token)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(found_lists)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user