mirror of
https://github.com/orhun/systeroid
synced 2024-10-01 13:13:32 +00:00
refactor(parser): process the parsed pairs in the 'title' module
This commit is contained in:
parent
764b706c87
commit
2d1b9daf4a
|
@ -6,6 +6,9 @@ pub enum Error {
|
|||
/// Error that might occur during I/O operations.
|
||||
#[error("IO error: `{0}`")]
|
||||
IoError(#[from] std::io::Error),
|
||||
/// Error that might occur while parsing documents.
|
||||
#[error("parse error: `{0}`")]
|
||||
ParseError(String),
|
||||
}
|
||||
|
||||
/// Type alias for the standard [`Result`] type.
|
||||
|
|
|
@ -5,5 +5,8 @@
|
|||
/// RST parser.
|
||||
pub mod parser;
|
||||
|
||||
/// Parsed title.
|
||||
pub mod title;
|
||||
|
||||
#[macro_use]
|
||||
extern crate pest_derive;
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#![allow(missing_docs)] // pest_derive does not have doc comments.
|
||||
#![allow(missing_docs)] // pest_derive does not generate doc comments
|
||||
|
||||
use crate::title::Title;
|
||||
use kparams_core::error::{Error, Result};
|
||||
use kparams_core::kernel::{Documentation, Parameter};
|
||||
use pest::Parser;
|
||||
use pest::Token;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Parser for the reStructuredText format.
|
||||
#[derive(Parser)]
|
||||
|
@ -13,37 +15,23 @@ impl RstParser {
|
|||
/// Parses the given reStructuredText input and returns the [`kernel documentation`].
|
||||
///
|
||||
/// [`kernel documentation`]: Documentation
|
||||
pub fn parse_docs(input: &str) -> Documentation {
|
||||
let rst_document = Self::parse(Rule::document, input).expect("failed to parse document");
|
||||
pub fn parse_docs(input: &str) -> Result<Documentation> {
|
||||
let mut kernel_parameters = Vec::new();
|
||||
let rst_document =
|
||||
Self::parse(Rule::document, input).map_err(|e| Error::ParseError(e.to_string()))?;
|
||||
let titles = rst_document
|
||||
.filter(|block| block.as_rule() == Rule::title)
|
||||
.map(|title| {
|
||||
(
|
||||
title.as_str().lines().next().unwrap(),
|
||||
title
|
||||
.tokens()
|
||||
.filter_map(|token| match token {
|
||||
Token::Start { rule, pos } | Token::End { rule, pos } => {
|
||||
if rule == Rule::title {
|
||||
Some(pos.pos())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<(&str, Vec<usize>)>>();
|
||||
for (i, (title, pos)) in titles.iter().enumerate() {
|
||||
assert_eq!(2, pos.len());
|
||||
kernel_parameters.push(if let Some(next_title) = titles.get(i + 1) {
|
||||
Parameter::new(*title, (input[pos[1]..next_title.1[0]]).as_ref())
|
||||
} else {
|
||||
Parameter::new(*title, (input[pos[1]..]).as_ref())
|
||||
});
|
||||
.filter_map(|pair| Title::try_from(pair).ok())
|
||||
.collect::<Vec<Title<'_>>>();
|
||||
for (i, title) in titles.iter().enumerate() {
|
||||
kernel_parameters.push(Parameter::new(
|
||||
title.value,
|
||||
if let Some(next_title) = titles.get(i + 1) {
|
||||
(input[title.end_pos..next_title.start_pos]).as_ref()
|
||||
} else {
|
||||
(input[title.end_pos..]).as_ref()
|
||||
},
|
||||
));
|
||||
}
|
||||
Documentation::new(kernel_parameters)
|
||||
Ok(Documentation::new(kernel_parameters))
|
||||
}
|
||||
}
|
||||
|
|
54
kparams-parser/src/title.rs
Normal file
54
kparams-parser/src/title.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use crate::parser::Rule;
|
||||
use kparams_core::error::Error as ErrorImpl;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Token;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// Title from the parsed RST document.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Title<'a> {
|
||||
/// Title value.
|
||||
pub value: &'a str,
|
||||
/// Start position of the title.
|
||||
pub start_pos: usize,
|
||||
/// End position of the title.
|
||||
pub end_pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<Pair<'a, Rule>> for Title<'a> {
|
||||
type Error = ErrorImpl;
|
||||
|
||||
fn try_from(pair: Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||
let mut title = Title::default();
|
||||
|
||||
// check if the rule matches
|
||||
if pair.as_rule() == Rule::title {
|
||||
return Err(ErrorImpl::ParseError(String::from(
|
||||
"parsed section is not a title",
|
||||
)));
|
||||
}
|
||||
|
||||
// set the actual title
|
||||
if let Some(value) = pair.as_str().lines().next() {
|
||||
title.value = value;
|
||||
} else {
|
||||
return Err(ErrorImpl::ParseError(String::from("invalid title")));
|
||||
}
|
||||
|
||||
// set token positions
|
||||
pair.tokens().for_each(|token| match token {
|
||||
Token::Start { rule, pos } => {
|
||||
if rule == Rule::title {
|
||||
title.start_pos = pos.pos();
|
||||
}
|
||||
}
|
||||
Token::End { rule, pos } => {
|
||||
if rule == Rule::title {
|
||||
title.end_pos = pos.pos();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(title)
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ pub fn run() -> Result<()> {
|
|||
let sysctl_docs = kernel_docs.join("admin-guide").join("sysctl");
|
||||
let kernel_section = reader::read_to_string(&sysctl_docs.join("kernel.rst"))?;
|
||||
|
||||
let kernel_section_docs = RstParser::parse_docs(&kernel_section);
|
||||
let kernel_section_docs = RstParser::parse_docs(&kernel_section)?;
|
||||
for kernel_parameter in kernel_section_docs.parameters {
|
||||
println!("## {}", kernel_parameter.name);
|
||||
println!("{}", kernel_parameter.description);
|
||||
|
|
Loading…
Reference in a new issue