diff options
author | Norbert Preining <norbert@preining.info> | 2020-05-28 03:03:21 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2020-05-28 03:03:21 +0000 |
commit | 745892fbddea56040139108277e728b53fd8fc11 (patch) | |
tree | 15e55e299b38fccdabce8364f1fbf4f02ef37994 /support/texlab/src/syntax/latex/parser.rs | |
parent | 195ca7e0c377d83455867bdd8e409d4e1cf024ea (diff) |
CTAN sync 202005280303
Diffstat (limited to 'support/texlab/src/syntax/latex/parser.rs')
-rw-r--r-- | support/texlab/src/syntax/latex/parser.rs | 177 |
1 files changed, 114 insertions, 63 deletions
diff --git a/support/texlab/src/syntax/latex/parser.rs b/support/texlab/src/syntax/latex/parser.rs index 40693071c2..4ace4fbcd6 100644 --- a/support/texlab/src/syntax/latex/parser.rs +++ b/support/texlab/src/syntax/latex/parser.rs @@ -1,62 +1,84 @@ use super::ast::*; +use crate::{ + protocol::{Range, RangeExt}, + syntax::{ + generic_ast::{Ast, AstNodeIndex}, + text::SyntaxNode, + }, +}; use std::iter::Peekable; -use std::sync::Arc; #[derive(Debug, PartialEq, Eq, Clone, Copy)] -enum LatexScope { +enum Scope { Root, Group, Options, } -pub struct LatexParser<I: Iterator<Item = LatexToken>> { +#[derive(Debug)] +pub struct Parser<I: Iterator<Item = Token>> { + tree: Ast<Node>, tokens: Peekable<I>, } -impl<I: Iterator<Item = LatexToken>> LatexParser<I> { +impl<I: Iterator<Item = Token>> Parser<I> { pub fn new(tokens: I) -> Self { - LatexParser { + Self { + tree: Ast::new(), tokens: tokens.peekable(), } } - pub fn root(&mut self) -> LatexRoot { - let children = self.content(LatexScope::Root); - LatexRoot::new(children) + pub fn parse(mut self) -> Tree { + let children = self.content(Scope::Root); + + let range = if children.is_empty() { + Range::new_simple(0, 0, 0, 0) + } else { + let start = self.tree[children[0]].start(); + let end = self.tree[children[children.len() - 1]].end(); + Range::new(start, end) + }; + + let root = self.tree.add_node(Node::Root(Root { range })); + self.connect(root, &children); + Tree { + inner: self.tree, + root, + } } - fn content(&mut self, scope: LatexScope) -> Vec<LatexContent> { + fn content(&mut self, scope: Scope) -> Vec<AstNodeIndex> { let mut children = Vec::new(); while let Some(ref token) = self.tokens.peek() { match token.kind { - LatexTokenKind::Word | LatexTokenKind::BeginOptions => { - children.push(LatexContent::Text(self.text(scope))); + TokenKind::Word | TokenKind::BeginOptions => { + children.push(self.text(scope)); } - LatexTokenKind::Command => { - children.push(LatexContent::Command(self.command())); + TokenKind::Command => { + children.push(self.command()); } - LatexTokenKind::Comma => { - let node = LatexComma::new(self.tokens.next().unwrap()); - children.push(LatexContent::Comma(Arc::new(node))); + TokenKind::Comma => { + children.push(self.comma()); } - LatexTokenKind::Math => { - children.push(LatexContent::Math(self.math())); + TokenKind::Math => { + children.push(self.math()); } - LatexTokenKind::BeginGroup => { - children.push(LatexContent::Group(self.group(LatexGroupKind::Group))); + TokenKind::BeginGroup => { + children.push(self.group(GroupKind::Group)); } - LatexTokenKind::EndGroup => { - if scope == LatexScope::Root { + TokenKind::EndGroup => { + if scope == Scope::Root { self.tokens.next(); } else { return children; } } - LatexTokenKind::EndOptions => { - if scope == LatexScope::Options { + TokenKind::EndOptions => { + if scope == Scope::Options { return children; } else { - children.push(LatexContent::Text(self.text(scope))); + children.push(self.text(scope)); } } } @@ -64,37 +86,17 @@ impl<I: Iterator<Item = LatexToken>> LatexParser<I> { children } - fn command(&mut self) -> Arc<LatexCommand> { - let name = self.tokens.next().unwrap(); - - let mut options = Vec::new(); - let mut args = Vec::new(); - while let Some(token) = self.tokens.peek() { - match token.kind { - LatexTokenKind::BeginGroup => { - args.push(self.group(LatexGroupKind::Group)); - } - LatexTokenKind::BeginOptions => { - options.push(self.group(LatexGroupKind::Options)); - } - _ => { - break; - } - } - } - Arc::new(LatexCommand::new(name, options, args)) - } - - fn group(&mut self, kind: LatexGroupKind) -> Arc<LatexGroup> { + fn group(&mut self, kind: GroupKind) -> AstNodeIndex { let left = self.tokens.next().unwrap(); let scope = match kind { - LatexGroupKind::Group => LatexScope::Group, - LatexGroupKind::Options => LatexScope::Options, + GroupKind::Group => Scope::Group, + GroupKind::Options => Scope::Options, }; + let children = self.content(scope); let right_kind = match kind { - LatexGroupKind::Group => LatexTokenKind::EndGroup, - LatexGroupKind::Options => LatexTokenKind::EndOptions, + GroupKind::Group => TokenKind::EndGroup, + GroupKind::Options => TokenKind::EndOptions, }; let right = if self.next_of_kind(right_kind) { @@ -103,33 +105,82 @@ impl<I: Iterator<Item = LatexToken>> LatexParser<I> { None }; - Arc::new(LatexGroup::new(left, children, right, kind)) + let end = right + .as_ref() + .map(SyntaxNode::end) + .or_else(|| children.last().map(|child| self.tree[*child].end())) + .unwrap_or_else(|| left.end()); + let range = Range::new(left.start(), end); + + let node = self.tree.add_node(Node::Group(Group { + range, + left, + kind, + right, + })); + self.connect(node, &children); + node } - fn text(&mut self, scope: LatexScope) -> Arc<LatexText> { + fn command(&mut self) -> AstNodeIndex { + let name = self.tokens.next().unwrap(); + let mut children = Vec::new(); + while let Some(token) = self.tokens.peek() { + match token.kind { + TokenKind::BeginGroup => children.push(self.group(GroupKind::Group)), + TokenKind::BeginOptions => children.push(self.group(GroupKind::Options)), + _ => break, + } + } + + let end = children + .last() + .map(|child| self.tree[*child].end()) + .unwrap_or_else(|| name.end()); + let range = Range::new(name.start(), end); + + let node = self.tree.add_node(Node::Command(Command { range, name })); + self.connect(node, &children); + node + } + + fn text(&mut self, scope: Scope) -> AstNodeIndex { let mut words = Vec::new(); while let Some(ref token) = self.tokens.peek() { let kind = token.kind; - let opts = kind == LatexTokenKind::EndOptions && scope != LatexScope::Options; - if kind == LatexTokenKind::Word || kind == LatexTokenKind::BeginOptions || opts { + let opts = kind == TokenKind::EndOptions && scope != Scope::Options; + if kind == TokenKind::Word || kind == TokenKind::BeginOptions || opts { words.push(self.tokens.next().unwrap()); } else { break; } } - Arc::new(LatexText::new(words)) + let range = Range::new(words[0].start(), words[words.len() - 1].end()); + self.tree.add_node(Node::Text(Text { range, words })) } - fn math(&mut self) -> Arc<LatexMath> { + fn comma(&mut self) -> AstNodeIndex { let token = self.tokens.next().unwrap(); - Arc::new(LatexMath::new(token)) + let range = token.range(); + self.tree.add_node(Node::Comma(Comma { range, token })) } - fn next_of_kind(&mut self, kind: LatexTokenKind) -> bool { - if let Some(ref token) = self.tokens.peek() { - token.kind == kind - } else { - false + fn math(&mut self) -> AstNodeIndex { + let token = self.tokens.next().unwrap(); + let range = token.range(); + self.tree.add_node(Node::Math(Math { range, token })) + } + + fn connect(&mut self, parent: AstNodeIndex, children: &[AstNodeIndex]) { + for child in children { + self.tree.add_edge(parent, *child); } } + + fn next_of_kind(&mut self, kind: TokenKind) -> bool { + self.tokens + .peek() + .filter(|token| token.kind == kind) + .is_some() + } } |