Compare commits
3 Commits
0bbc6e2a62
...
5616237eea
Author | SHA1 | Date |
---|---|---|
mars | 5616237eea | |
mars | 3091cc09f4 | |
mars | 9d68e04d75 |
|
@ -0,0 +1 @@
|
|||
("unstyled" bold "bold" (red "bold red") italic "bold italic")
|
52
src/ast.rs
52
src/ast.rs
|
@ -124,7 +124,7 @@ impl<'a> AstBuilder<'a> {
|
|||
let span = self.lexer.span();
|
||||
if let TokenKind::Newline = token {
|
||||
self.current_row_idx += 1;
|
||||
self.current_row_start = span.start;
|
||||
self.current_row_start = span.end;
|
||||
} else if let TokenKind::Error = token {
|
||||
let range = self.span_to_range(span);
|
||||
break Err(self.with_source(ParseErrorKind::InvalidToken, range));
|
||||
|
@ -190,23 +190,27 @@ impl<'a> AstBuilder<'a> {
|
|||
}
|
||||
|
||||
pub fn parse_list_from(&mut self, mut token: Token) -> ParseResult<Vec<Value>> {
|
||||
if let TokenKind::Symbol = token.kind {
|
||||
let start = token.range.start.clone();
|
||||
let id = self.token_to_string(token)?;
|
||||
let body = self.parse_tag_body()?;
|
||||
let end = self.idx_to_position(self.lexer.span().end);
|
||||
return Ok(vec![Value {
|
||||
inner: ValueKind::Tag(Tag { id, body }),
|
||||
source: self.source.to_owned(),
|
||||
range: start..end,
|
||||
}]);
|
||||
}
|
||||
|
||||
let mut vals = Vec::new();
|
||||
|
||||
while let Some(val) = self.parse_value_from(token)? {
|
||||
vals.push(val);
|
||||
token = self.next()?;
|
||||
loop {
|
||||
if let TokenKind::Symbol = token.kind {
|
||||
let start = token.range.start.clone();
|
||||
let id = self.token_to_string(token)?;
|
||||
let body = self.parse_tag_body()?;
|
||||
let end = self.idx_to_position(self.lexer.span().end);
|
||||
let val = Value {
|
||||
inner: ValueKind::Tag(Tag { id, body }),
|
||||
source: self.source.to_owned(),
|
||||
range: start..end,
|
||||
};
|
||||
vals.push(val);
|
||||
break;
|
||||
} else if let Some(val) = self.parse_value_from(token)? {
|
||||
vals.push(val);
|
||||
token = self.next()?;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(vals)
|
||||
|
@ -284,7 +288,7 @@ impl<T: Debug + Display> Display for WithSource<T> {
|
|||
|
||||
let spaces: String = std::iter::repeat(" ").take(start).collect();
|
||||
let carats: String = std::iter::repeat("^").take(end - start).collect();
|
||||
writeln!(f, " |{}{}", spaces, carats)?;
|
||||
writeln!(f, " | {}{}", spaces, carats)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -412,18 +416,18 @@ pub enum ParseErrorKind {
|
|||
|
||||
impl Display for ParseErrorKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "Error: ")?;
|
||||
write!(f, "Parse error: ")?;
|
||||
|
||||
use ParseErrorKind::*;
|
||||
match self {
|
||||
InvalidToken => write!(f, "Invalid token"),
|
||||
DuplicateArgument(name) => write!(f, "Duplicate {} argument", name),
|
||||
UnmatchedParen => write!(f, "Unmatched parentheses"),
|
||||
InvalidToken => write!(f, "invalid token"),
|
||||
DuplicateArgument(name) => write!(f, "duplicate {} argument", name),
|
||||
UnmatchedParen => write!(f, "unmatched parentheses"),
|
||||
UnexpectedToken(kind, Some(expected)) => {
|
||||
write!(f, "Unexpected {:?} token (expected {:?})", kind, expected)
|
||||
write!(f, "unexpected {:?} token (expected {:?})", kind, expected)
|
||||
}
|
||||
UnexpectedToken(kind, None) => write!(f, "Unexpected token {:?}", kind),
|
||||
UnexpectedEof => write!(f, "Unexpected end-of-file"),
|
||||
UnexpectedToken(kind, None) => write!(f, "unexpected token {:?}", kind),
|
||||
UnexpectedEof => write!(f, "unexpected end-of-file"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -12,18 +12,27 @@ use style::Stylesheet;
|
|||
fn main() {
|
||||
let src_path = std::env::args().nth(1).unwrap();
|
||||
let src = std::fs::read_to_string(src_path).unwrap();
|
||||
|
||||
|
||||
let lexer = ast::TokenKind::lexer(&src);
|
||||
let tokens: Vec<_> = lexer.collect();
|
||||
println!("{:?}", tokens);
|
||||
|
||||
let source = std::sync::Arc::new(ast::Source::from_string(src.clone()));
|
||||
let mut ast_builder = ast::AstBuilder::new(&source);
|
||||
|
||||
match ast_builder.expect_value() {
|
||||
Ok(body) => println!("{:#?}", body),
|
||||
let body = match ast_builder.parse_tag_body() {
|
||||
Ok(body) => body,
|
||||
Err(e) => panic!("Parse error:\n{}", e),
|
||||
}
|
||||
};
|
||||
|
||||
println!("{:#?}", body);
|
||||
|
||||
let style = text::TextStyle::default();
|
||||
let text = match text::StyledText::parse(&style, &body.children) {
|
||||
Ok(text) => text,
|
||||
Err(e) => panic!("Text parse error:\n{}", e),
|
||||
};
|
||||
|
||||
println!("{:#?}", text);
|
||||
|
||||
let options = lexpr::parse::Options::new()
|
||||
.with_string_syntax(lexpr::parse::StringSyntax::Elisp)
|
||||
|
|
64
src/text.rs
64
src/text.rs
|
@ -1,5 +1,9 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use strum::EnumString;
|
||||
|
||||
use crate::ast::{self, WithSource};
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, EnumString)]
|
||||
#[strum(serialize_all = "kebab-case", ascii_case_insensitive)]
|
||||
pub enum TextTagKind {
|
||||
|
@ -99,7 +103,63 @@ impl TextStyle {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct StyledText {
|
||||
pub text: String,
|
||||
pub struct StyledString {
|
||||
pub string: String,
|
||||
pub style: TextStyle,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
|
||||
pub struct StyledText {
|
||||
pub strings: Vec<StyledString>,
|
||||
}
|
||||
|
||||
impl StyledText {
|
||||
pub fn concat(&mut self, mut other: Self) {
|
||||
self.strings.append(&mut other.strings);
|
||||
}
|
||||
|
||||
pub fn parse(style: &TextStyle, vals: &[ast::Value]) -> Result<Self, TextParseError> {
|
||||
let mut text = Self::default();
|
||||
for val in vals.iter() {
|
||||
match &val.inner {
|
||||
ast::ValueKind::String(string) => text.strings.push(StyledString {
|
||||
string: string.clone(),
|
||||
style: style.clone(),
|
||||
}),
|
||||
ast::ValueKind::List(items) => text.concat(Self::parse(style, items)?),
|
||||
ast::ValueKind::Tag(tag) => text.concat(Self::parse_tag(style, tag)?),
|
||||
_ => return Err(val.map(TextParseErrorKind::UnexpectedSymbol)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(text)
|
||||
}
|
||||
|
||||
pub fn parse_tag(style: &TextStyle, tag: &ast::Tag) -> Result<Self, TextParseError> {
|
||||
let kind = TextTagKind::from_str(&tag.id)
|
||||
.map_err(|_| tag.id.map(TextParseErrorKind::InvalidTag))?;
|
||||
let mut style = style.clone();
|
||||
style.apply_tag(kind);
|
||||
Self::parse(&style, &tag.body.children)
|
||||
}
|
||||
}
|
||||
|
||||
pub type TextParseError = WithSource<TextParseErrorKind>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TextParseErrorKind {
|
||||
InvalidTag,
|
||||
UnexpectedSymbol,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for TextParseErrorKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "Text parse error: ")?;
|
||||
|
||||
use TextParseErrorKind::*;
|
||||
match self {
|
||||
InvalidTag => write!(f, "invalid tag"),
|
||||
UnexpectedSymbol => write!(f, "unexpected symbol"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue