summaryrefslogtreecommitdiff
path: root/support/texlab/src/syntax/latex/parser.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/syntax/latex/parser.rs')
-rw-r--r--support/texlab/src/syntax/latex/parser.rs177
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()
+ }
}