sdlang/lib.rs
1//! An [SDLang][sdlang] parser library.
2//!
3//! [SDLang][sdlang] is a simple and concise way to textually represent data.
4//! It has an XML-like structure - tags, values, and attributes - which makes
5//! it a versatily choice for data serialization, configuration files, or
6//! declarative languages. Its syntax was inspired by the C family of languages
7//! (C/C++, C#, D, Java, ...).
8//!
9//! Here's an example from the official website:
10//! ```sdlang
11//! // This is a node with a single string value
12//! title "Hello, World"
13//!
14//! // Multiple values are supported, too
15//! bookmarks 12 15 188 1234
16//!
17//! // Nodes can have attributes
18//! author "Peter Parker" email="peter@example.org" active=true
19//!
20//! // Nodes can be arbitrarily nested
21//! contents {
22//! section "First Section" {
23//! paragraph "This is the first paragraph"
24//! paragraph "This is the second paragraph"
25//! }
26//! }
27//!
28//! // Anonymous nodes are supported
29//! "This text is the value of an anonymous node!"
30//!
31//! // This makes things like matrix definiotns very convenient
32//! matrix {
33//! 1 0 0
34//! 0 1 0
35//! 0 0 1
36//! }
37//! ```
38//!
39//! Parsing is made as easy as this:
40//! ```rust
41//! extern crate sdlang;
42//!
43//! // Prints `tag hello_world: "text"`
44//! println!("{}", sdlang::parse_text("hello_world \"text\"").unwrap());
45//! ```
46//! Note that all SDLang-related types (i.e `Tag`, `Attribute` and `Value`)
47//! implement `FromStr` so that they can be used with `str::parse`. Note,
48//! however, that in order to parse a whole file, which may have multiple root
49//! tags, use `parse_text` or `parse_file`.
50//!
51//! [sdlang]: https://sdlang.org "Official SDLang Website"
52
53// Crates
54extern crate base64;
55extern crate chrono;
56extern crate itertools;
57extern crate pest;
58#[macro_use] extern crate pest_derive;
59
60// Modules
61mod grammar;
62mod types;
63mod parse;
64
65// Public types
66pub use grammar::{Error, ParseRes as Result};
67pub use types::{Value, Attribute, Tag, Date, DateTime};
68
69// Internal usage here
70use std::{io, io::Read};
71
72/// Reads everything from the given Reader and parses it.
73///
74/// Look at `parse_text` for more information.
75///
76/// The reader is internally buffered using `std::io::BufReader`.
77pub fn parse_file<R>(data: R) -> io::Result<Result<Tag>>
78where R: io::Read {
79 let mut res = String::new();
80 io::BufReader::new(data).read_to_string(&mut res)?;
81 Ok(parse_text(res.as_str()))
82}
83
84/// Parses the given text into a root tag.
85///
86/// The name of the root tag is `""` (nothing); It has no namespace, values, or
87/// attributes; it only has a list of child tags.
88pub fn parse_text(data: &str) -> Result<Tag> {
89 Ok(Tag::new(String::new())
90 .tags(grammar::parse(grammar::Rule::tagtree, data)
91 .and_then(parse::tagtree)?))
92}