Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--lib/ungrammar/src/error.rs2
-rw-r--r--lib/ungrammar/src/lib.rs36
2 files changed, 37 insertions, 1 deletions
diff --git a/lib/ungrammar/src/error.rs b/lib/ungrammar/src/error.rs
index a7a62d0cc0..6cc86f52f9 100644
--- a/lib/ungrammar/src/error.rs
+++ b/lib/ungrammar/src/error.rs
@@ -3,8 +3,10 @@ use std::fmt;
use crate::lexer::Location;
+/// A type alias for std's Result with the Error as our error type.
pub type Result<T, E = Error> = std::result::Result<T, E>;
+/// An error encountered when parsing a Grammar.
#[derive(Debug)]
pub struct Error {
pub(crate) message: String,
diff --git a/lib/ungrammar/src/lib.rs b/lib/ungrammar/src/lib.rs
index 228952389f..7d7c14f535 100644
--- a/lib/ungrammar/src/lib.rs
+++ b/lib/ungrammar/src/lib.rs
@@ -6,6 +6,11 @@
//! See this
//! [introductory post](https://rust-analyzer.github.io/blog/2020/10/24/introducing-ungrammar.html)
//! for details.
+
+#![deny(missing_debug_implementations)]
+#![deny(missing_docs)]
+#![deny(rust_2018_idioms)]
+
mod error;
mod lexer;
mod parser;
@@ -14,16 +19,21 @@ use std::{ops, str::FromStr};
pub use error::{Error, Result};
+/// Returns a Rust grammar.
pub fn rust_grammar() -> Grammar {
let src = include_str!("../rust.ungram");
src.parse().unwrap()
}
+/// A node, like `A = 'b' | 'c'`.
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash, PartialOrd, Ord)]
pub struct Node(usize);
+
+/// A token, denoted with single quotes, like `'+'` or `'struct'`.
#[derive(Eq, PartialEq, Debug, Copy, Clone, Hash, PartialOrd, Ord)]
pub struct Token(usize);
+/// An Ungrammar grammar.
#[derive(Default, Debug)]
pub struct Grammar {
nodes: Vec<NodeData>,
@@ -39,10 +49,12 @@ impl FromStr for Grammar {
}
impl Grammar {
+ /// Returns an iterator over all nodes in the grammar.
pub fn iter(&self) -> impl Iterator<Item = Node> + '_ {
(0..self.nodes.len()).map(Node)
}
+ /// Returns an iterator over all tokens in the grammar.
pub fn tokens(&self) -> impl Iterator<Item = Token> + '_ {
(0..self.tokens.len()).map(Token)
}
@@ -62,25 +74,47 @@ impl ops::Index<Token> for Grammar {
}
}
+/// Data about a node.
#[derive(Debug)]
pub struct NodeData {
+ /// The name of the node.
+ ///
+ /// In the rule `A = 'b' | 'c'`, this is `"A"`.
pub name: String,
+ /// The rule for this node.
+ ///
+ /// In the rule `A = 'b' | 'c'`, this represents `'b' | 'c'`.
pub rule: Rule,
}
+/// Data about a token.
#[derive(Debug)]
pub struct TokenData {
+ /// The name of the token.
pub name: String,
}
+/// A production rule.
#[derive(Debug, Eq, PartialEq)]
pub enum Rule {
- Labeled { label: String, rule: Box<Rule> },
+ /// A labeled rule, like `a:B` (`"a"` is the label, `B` is the rule).
+ Labeled {
+ /// The label.
+ label: String,
+ /// The rule.
+ rule: Box<Rule>,
+ },
+ /// A node, like `A`.
Node(Node),
+ /// A token, like `'struct'`.
Token(Token),
+ /// A sequence of rules, like `'while' '(' Expr ')' Stmt`.
Seq(Vec<Rule>),
+ /// An alternative between many rules, like `'+' | '-' | '*' | '/'`.
Alt(Vec<Rule>),
+ /// An optional rule, like `A?`.
Opt(Box<Rule>),
+ /// An repeated rule, like `A*`.
Rep(Box<Rule>),
}