mod annotation;
mod block;
mod choice;
mod content;
mod decl;
mod divert;
mod doc_comment;
mod expr;
mod family;
mod source_file;
#[cfg(test)]
mod tests;
use crate::SyntaxKind::{self, ERROR};
use crate::lexer;
use rowan::GreenNode;
#[derive(Clone, PartialEq, Eq)]
pub struct Parse {
green: GreenNode,
errors: Vec<ParseError>,
}
impl Parse {
#[must_use]
pub fn green(&self) -> &GreenNode {
&self.green
}
#[must_use]
pub fn syntax(&self) -> crate::SyntaxNode {
crate::SyntaxNode::new_root(self.green.clone())
}
#[must_use]
pub fn errors(&self) -> &[ParseError] {
&self.errors
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseError {
pub message: String,
pub range: rowan::TextRange,
}
#[must_use]
pub fn parse(source: &str) -> Parse {
let raw_tokens = lexer::lex(source);
let mut p = Parser::new(&raw_tokens);
source_file::source_file(&mut p);
let green = p.builder.finish();
Parse {
green,
errors: p.errors,
}
}
pub fn parse_with_cache(source: &str, cache: &mut rowan::NodeCache) -> Parse {
let raw_tokens = lexer::lex(source);
let mut p = Parser::with_cache(&raw_tokens, cache);
source_file::source_file(&mut p);
let green = p.builder.finish();
Parse {
green,
errors: p.errors,
}
}
const MAX_DEPTH: u32 = 256;
pub(crate) struct Parser<'t, 'c> {
tokens: &'t [(SyntaxKind, &'t str)],
pos: usize,
depth: u32,
non_trivia: Vec<usize>,
builder: rowan::GreenNodeBuilder<'c>,
errors: Vec<ParseError>,
}
impl<'t> Parser<'t, 'static> {
fn new(tokens: &'t [(SyntaxKind, &'t str)]) -> Self {
let non_trivia = Self::build_non_trivia(tokens);
Self {
tokens,
pos: 0,
depth: 0,
non_trivia,
builder: rowan::GreenNodeBuilder::new(),
errors: Vec::new(),
}
}
}
impl<'t, 'c> Parser<'t, 'c> {
fn with_cache(tokens: &'t [(SyntaxKind, &'t str)], cache: &'c mut rowan::NodeCache) -> Self {
let non_trivia = Self::build_non_trivia(tokens);
Self {
tokens,
pos: 0,
depth: 0,
non_trivia,
builder: rowan::GreenNodeBuilder::with_cache(cache),
errors: Vec::new(),
}
}
fn build_non_trivia(tokens: &[(SyntaxKind, &str)]) -> Vec<usize> {
tokens
.iter()
.enumerate()
.filter(|(_, (k, _))| !k.is_trivia())
.map(|(i, _)| i)
.collect()
}
fn enter_depth(&mut self) -> bool {
if self.depth >= MAX_DEPTH {
self.error("maximum nesting depth exceeded".into());
false
} else {
self.depth += 1;
true
}
}
fn exit_depth(&mut self) {
self.depth -= 1;
}
fn current(&self) -> SyntaxKind {
self.nth(0)
}
fn nth(&self, n: usize) -> SyntaxKind {
let start = self.non_trivia.partition_point(|&idx| idx < self.pos);
let target = start + n;
if target < self.non_trivia.len() {
self.tokens[self.non_trivia[target]].0
} else {
SyntaxKind::EOF
}
}
fn nth_raw(&self, n: usize) -> SyntaxKind {
self.tokens
.get(self.pos + n)
.map_or(SyntaxKind::EOF, |&(k, _)| k)
}
fn at(&self, kind: SyntaxKind) -> bool {
self.current() == kind
}
fn at_eof(&self) -> bool {
self.current() == SyntaxKind::EOF
}
fn pos(&self) -> usize {
self.pos
}
fn bump(&mut self) {
if self.pos < self.tokens.len() {
let (kind, text) = self.tokens[self.pos];
self.builder.token(rowan::SyntaxKind(kind as u16), text);
self.pos += 1;
}
}
fn eat(&mut self, kind: SyntaxKind) -> bool {
self.skip_ws();
if self.current() == kind {
self.bump();
true
} else {
false
}
}
fn expect(&mut self, kind: SyntaxKind) {
if !self.eat(kind) {
self.error(format!("expected {kind:?}, found {:?}", self.current()));
}
}
fn skip_ws(&mut self) {
while self.pos < self.tokens.len() && self.tokens[self.pos].0.is_trivia() {
self.bump();
}
}
fn skip_ws_and_newlines(&mut self) {
while self.pos < self.tokens.len()
&& (self.tokens[self.pos].0.is_trivia()
|| self.tokens[self.pos].0 == SyntaxKind::NEWLINE)
{
self.bump();
}
}
fn peek_skip_nl(&self) -> SyntaxKind {
let mut i = self.pos;
while i < self.tokens.len()
&& (self.tokens[i].0.is_trivia() || self.tokens[i].0 == SyntaxKind::NEWLINE)
{
i += 1;
}
self.tokens.get(i).map_or(SyntaxKind::EOF, |&(k, _)| k)
}
fn start_node(&mut self, kind: SyntaxKind) {
self.builder.start_node(rowan::SyntaxKind(kind as u16));
}
fn start_node_at(&mut self, checkpoint: rowan::Checkpoint, kind: SyntaxKind) {
self.builder
.start_node_at(checkpoint, rowan::SyntaxKind(kind as u16));
}
fn finish_node(&mut self) {
self.builder.finish_node();
}
fn checkpoint(&self) -> rowan::Checkpoint {
self.builder.checkpoint()
}
fn error(&mut self, message: String) {
let upto = self.pos.min(self.tokens.len());
let start: usize = self.tokens[..upto].iter().map(|(_, t)| t.len()).sum();
let len: usize = self.tokens.get(self.pos).map_or(0, |(_, t)| t.len());
let start = rowan::TextSize::from(u32::try_from(start).unwrap_or(u32::MAX));
let len = rowan::TextSize::from(u32::try_from(len).unwrap_or(u32::MAX));
self.errors.push(ParseError {
message,
range: rowan::TextRange::at(start, len),
});
}
fn error_recover(&mut self, message: &str) {
self.error(message.to_owned());
self.start_node(ERROR);
if self.pos < self.tokens.len() {
self.bump();
}
self.finish_node();
}
}