mirror of
https://github.com/typst/typst
synced 2025-05-13 12:36:23 +08:00
Prettify peeking and rearrange syntax/parsing modules 🧶
This commit is contained in:
parent
ecf0ff4d05
commit
b4be25e43b
@ -1,11 +1,14 @@
|
||||
use super::prelude::*;
|
||||
use std::iter::Peekable;
|
||||
use std::slice::Iter;
|
||||
use super::prelude::*;
|
||||
|
||||
/// Implement the function trait more concisely.
|
||||
#[macro_export]
|
||||
macro_rules! function {
|
||||
(data: $ident:ident, $($tts:tt)*) => {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::func::prelude::*;
|
||||
|
||||
impl Function for $ident {
|
||||
function!(@parse $ident, $($tts)*);
|
||||
}
|
||||
@ -64,7 +67,7 @@ macro_rules! parse {
|
||||
|
||||
(optional: $body:expr, $ctx:expr) => {
|
||||
if let Some(body) = $body {
|
||||
Some($crate::parsing::parse(body, $ctx)?)
|
||||
Some($crate::syntax::parse(body, $ctx)?)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -72,7 +75,7 @@ macro_rules! parse {
|
||||
|
||||
(required: $body:expr, $ctx:expr) => {
|
||||
if let Some(body) = $body {
|
||||
$crate::parsing::parse(body, $ctx)?
|
||||
$crate::syntax::parse(body, $ctx)?
|
||||
} else {
|
||||
err!("expected body");
|
||||
}
|
||||
@ -83,7 +86,7 @@ macro_rules! parse {
|
||||
#[macro_export]
|
||||
macro_rules! err {
|
||||
($($tts:tt)*) => {
|
||||
return Err(ParseError::new(format!($($tts)*)));
|
||||
return Err($crate::syntax::ParseError::new(format!($($tts)*)));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,7 @@ use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use crate::layout::{Layout, LayoutContext, Alignment, LayoutResult, MultiLayout};
|
||||
use crate::parsing::{ParseContext, ParseResult};
|
||||
use crate::style::TextStyle;
|
||||
use crate::syntax::{FuncHeader, SyntaxTree};
|
||||
use self::prelude::*;
|
||||
|
||||
#[macro_use]
|
||||
mod helpers;
|
||||
@ -18,9 +15,10 @@ pub mod prelude {
|
||||
pub use crate::func::{Command, CommandList, Function};
|
||||
pub use crate::layout::{layout_tree, Layout, LayoutContext, MultiLayout};
|
||||
pub use crate::layout::{Flow, Alignment, LayoutError, LayoutResult};
|
||||
pub use crate::parsing::{parse, ParseContext, ParseError, ParseResult};
|
||||
pub use crate::syntax::{Expression, FuncHeader, SyntaxTree};
|
||||
pub use crate::syntax::{parse, ParseContext, ParseError, ParseResult};
|
||||
pub use crate::size::{Size, Size2D, SizeBox};
|
||||
pub use crate::style::{PageStyle, TextStyle};
|
||||
pub use super::helpers::*;
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,8 @@ use toddle::query::{FontLoader, FontProvider, SharedFontLoader};
|
||||
use crate::func::Scope;
|
||||
use crate::layout::{layout_tree, LayoutContext, MultiLayout};
|
||||
use crate::layout::{Alignment, Flow, LayoutError, LayoutResult, LayoutSpace};
|
||||
use crate::parsing::{parse, ParseContext, ParseError, ParseResult};
|
||||
use crate::syntax::{SyntaxTree, parse, ParseContext, ParseError, ParseResult};
|
||||
use crate::style::{PageStyle, TextStyle};
|
||||
use crate::syntax::SyntaxTree;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
@ -33,7 +32,6 @@ pub mod export;
|
||||
pub mod func;
|
||||
pub mod layout;
|
||||
pub mod library;
|
||||
pub mod parsing;
|
||||
pub mod size;
|
||||
pub mod style;
|
||||
pub mod syntax;
|
||||
|
@ -6,6 +6,12 @@ use std::fmt::{self, Display, Formatter};
|
||||
use crate::func::Function;
|
||||
use crate::size::Size;
|
||||
|
||||
mod tokens;
|
||||
mod parsing;
|
||||
|
||||
pub use tokens::{tokenize, Tokens};
|
||||
pub use parsing::{parse, ParseContext, ParseError, ParseResult};
|
||||
|
||||
/// A logical unit of the incoming text stream.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Token<'s> {
|
@ -1,16 +1,11 @@
|
||||
//! Parsing of source code into token streams and syntax trees.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use unicode_xid::UnicodeXID;
|
||||
|
||||
use crate::func::{Function, Scope};
|
||||
use crate::size::Size;
|
||||
use crate::syntax::*;
|
||||
|
||||
mod tokens;
|
||||
|
||||
pub use tokens::{tokenize, Tokens};
|
||||
use super::*;
|
||||
|
||||
/// Parses source code into a syntax tree given a context.
|
||||
#[inline]
|
||||
@ -222,7 +217,7 @@ impl<'s> Parser<'s> {
|
||||
// Find out the string which makes the body of this function.
|
||||
let (start, end) = self
|
||||
.tokens
|
||||
.current_index()
|
||||
.string_index()
|
||||
.and_then(|index| {
|
||||
find_closing_bracket(&self.src[index..]).map(|end| (index, index + end))
|
||||
})
|
||||
@ -233,7 +228,7 @@ impl<'s> Parser<'s> {
|
||||
let body = parser(&header, Some(body_string), self.ctx)?;
|
||||
|
||||
// Skip to the end of the function in the token stream.
|
||||
self.tokens.goto(end);
|
||||
self.tokens.set_string_index(end);
|
||||
|
||||
// Now the body should be closed.
|
||||
assert!(self.tokens.next() == Some(Token::RightBracket));
|
||||
@ -377,13 +372,13 @@ impl<'s> PeekableTokens<'s> {
|
||||
}
|
||||
|
||||
/// The index of the first character of the next token in the source string.
|
||||
fn current_index(&mut self) -> Option<usize> {
|
||||
self.tokens.chars.current_index()
|
||||
fn string_index(&mut self) -> Option<usize> {
|
||||
self.tokens.chars.string_index()
|
||||
}
|
||||
|
||||
/// Go to a new position in the underlying string.
|
||||
fn goto(&mut self, index: usize) {
|
||||
self.tokens.chars.goto(index);
|
||||
fn set_string_index(&mut self, index: usize) {
|
||||
self.tokens.chars.set_string_index(index);
|
||||
self.peeked = None;
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
use std::str::CharIndices;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::syntax::*;
|
||||
use super::*;
|
||||
|
||||
/// Builds an iterator over the tokens of the source code.
|
||||
#[inline]
|
||||
@ -223,7 +221,7 @@ impl<'s> Iterator for Tokens<'s> {
|
||||
// Find out when the word ends.
|
||||
let mut end = (next_pos, next);
|
||||
while let Some((index, c)) = self.chars.peek() {
|
||||
let second = self.chars.peek_second().map(|p| p.1);
|
||||
let second = self.chars.peekn(1).map(|p| p.1);
|
||||
|
||||
// Whether the next token is still from the text or not.
|
||||
let continues = match c {
|
||||
@ -266,66 +264,53 @@ fn is_newline_char(character: char) -> bool {
|
||||
/// A (index, char) iterator with double lookahead.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PeekableChars<'s> {
|
||||
offset: usize,
|
||||
string: &'s str,
|
||||
chars: CharIndices<'s>,
|
||||
peek1: Option<Option<(usize, char)>>,
|
||||
peek2: Option<Option<(usize, char)>>,
|
||||
base: usize,
|
||||
peeked: SmallVec<[Option<(usize, char)>; 2]>,
|
||||
}
|
||||
|
||||
impl<'s> PeekableChars<'s> {
|
||||
/// Create a new iterator from a string.
|
||||
pub fn new(string: &'s str) -> PeekableChars<'s> {
|
||||
PeekableChars {
|
||||
offset: 0,
|
||||
string,
|
||||
chars: string.char_indices(),
|
||||
peek1: None,
|
||||
peek2: None,
|
||||
base: 0,
|
||||
peeked: SmallVec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Peek at the next element.
|
||||
pub fn peek(&mut self) -> Option<(usize, char)> {
|
||||
match self.peek1 {
|
||||
Some(peeked) => peeked,
|
||||
None => {
|
||||
let next = self.next_inner();
|
||||
self.peek1 = Some(next);
|
||||
next
|
||||
}
|
||||
}
|
||||
self.peekn(0)
|
||||
}
|
||||
|
||||
/// Peek at the element after the next element.
|
||||
pub fn peek_second(&mut self) -> Option<(usize, char)> {
|
||||
match self.peek2 {
|
||||
Some(peeked) => peeked,
|
||||
None => {
|
||||
self.peek();
|
||||
let next = self.next_inner();
|
||||
self.peek2 = Some(next);
|
||||
next
|
||||
}
|
||||
pub fn peekn(&mut self, n: usize) -> Option<(usize, char)> {
|
||||
while self.peeked.len() <= n {
|
||||
let next = self.next_inner();
|
||||
self.peeked.push(next);
|
||||
}
|
||||
|
||||
self.peeked[n]
|
||||
}
|
||||
|
||||
/// Return the next value of the inner iterator mapped with the offset.
|
||||
pub fn next_inner(&mut self) -> Option<(usize, char)> {
|
||||
self.chars.next().map(|(i, c)| (i + self.offset, c))
|
||||
self.chars.next().map(|(i, c)| (i + self.base, c))
|
||||
}
|
||||
|
||||
/// The index of the first character of the next token in the source string.
|
||||
pub fn current_index(&mut self) -> Option<usize> {
|
||||
pub fn string_index(&mut self) -> Option<usize> {
|
||||
self.peek().map(|p| p.0)
|
||||
}
|
||||
|
||||
/// Go to a new position in the underlying string.
|
||||
pub fn goto(&mut self, index: usize) {
|
||||
self.offset = index;
|
||||
pub fn set_string_index(&mut self, index: usize) {
|
||||
self.chars = self.string[index..].char_indices();
|
||||
self.peek1 = None;
|
||||
self.peek2 = None;
|
||||
self.base = index;
|
||||
self.peeked.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,12 +318,10 @@ impl Iterator for PeekableChars<'_> {
|
||||
type Item = (usize, char);
|
||||
|
||||
fn next(&mut self) -> Option<(usize, char)> {
|
||||
match self.peek1.take() {
|
||||
Some(value) => {
|
||||
self.peek1 = self.peek2.take();
|
||||
value
|
||||
}
|
||||
None => self.next_inner(),
|
||||
if !self.peeked.is_empty() {
|
||||
self.peeked.remove(0)
|
||||
} else {
|
||||
self.next_inner()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user