summaryrefslogtreecommitdiff
path: root/support/texlab/crates/syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates/syntax/src')
-rw-r--r--support/texlab/crates/syntax/src/bibtex.rs299
-rw-r--r--support/texlab/crates/syntax/src/bibtex/cst.rs244
-rw-r--r--support/texlab/crates/syntax/src/bibtex/kind.rs43
-rw-r--r--support/texlab/crates/syntax/src/lib.rs13
4 files changed, 299 insertions, 300 deletions
diff --git a/support/texlab/crates/syntax/src/bibtex.rs b/support/texlab/crates/syntax/src/bibtex.rs
index b568fbf8e8..97ff6f6150 100644
--- a/support/texlab/crates/syntax/src/bibtex.rs
+++ b/support/texlab/crates/syntax/src/bibtex.rs
@@ -1,57 +1,19 @@
-use rowan::{ast::AstNode, NodeOrToken};
+mod cst;
+mod kind;
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
-#[allow(non_camel_case_types)]
-#[repr(u16)]
-pub enum SyntaxKind {
- WHITESPACE,
- JUNK,
- L_DELIM,
- R_DELIM,
- L_CURLY,
- R_CURLY,
- COMMA,
- POUND,
- QUOTE,
- EQ,
- TYPE,
- WORD,
- NAME,
- INTEGER,
- NBSP,
- ACCENT_NAME,
- COMMAND_NAME,
-
- PREAMBLE,
- STRING,
- ENTRY,
- FIELD,
- VALUE,
- LITERAL,
- JOIN,
- ACCENT,
- COMMAND,
- CURLY_GROUP,
- QUOTE_GROUP,
- ROOT,
-}
-
-pub use SyntaxKind::*;
-
-impl From<SyntaxKind> for rowan::SyntaxKind {
- fn from(kind: SyntaxKind) -> Self {
- Self(kind as u16)
- }
-}
+pub use self::{
+ cst::*,
+ kind::SyntaxKind::{self, *},
+};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
-pub enum Lang {}
+pub enum BibtexLanguage {}
-impl rowan::Language for Lang {
+impl rowan::Language for BibtexLanguage {
type Kind = SyntaxKind;
fn kind_from_raw(raw: rowan::SyntaxKind) -> Self::Kind {
- assert!(raw.0 <= SyntaxKind::ROOT as u16);
+ assert!(raw.0 <= ROOT as u16);
unsafe { std::mem::transmute::<u16, SyntaxKind>(raw.0) }
}
@@ -60,245 +22,8 @@ impl rowan::Language for Lang {
}
}
-pub type SyntaxNode = rowan::SyntaxNode<Lang>;
-
-pub type SyntaxToken = rowan::SyntaxToken<Lang>;
-
-pub type SyntaxElement = rowan::SyntaxElement<Lang>;
-
-macro_rules! ast_node {
- (name: $name:ident, kinds: [$($kind:pat),+], traits: [$($trait: ident),*]) => {
- #[derive(Clone)]
- pub struct $name {
- node: SyntaxNode,
- }
-
- impl AstNode for $name {
- type Language = Lang;
-
- fn can_cast(kind: SyntaxKind) -> bool {
- match kind {
- $($kind => true,)+
- _ => false,
- }
- }
-
- fn cast(node: SyntaxNode) -> Option<Self>
- where
- Self: Sized,
- {
- match node.kind() {
- $($kind => Some(Self { node}),)+
- _ => None,
- }
- }
-
- fn syntax(&self) -> &SyntaxNode {
- &self.node
- }
- }
-
- $(
- impl $trait for $name { }
- )*
- };
-}
-
-macro_rules! ast_node_enum {
- (name: $name:ident, variants: [$($variant:ident),+]) => {
- #[derive(Clone)]
- pub enum $name {
- $($variant($variant),)*
- }
-
- impl AstNode for $name {
- type Language = Lang;
-
- fn can_cast(kind: SyntaxKind) -> bool {
- false $(|| $variant::can_cast(kind))+
- }
-
- fn cast(node: SyntaxNode) -> Option<Self>
- where
- Self: Sized,
- {
- None $(.or_else(|| $variant::cast(node.clone()).map(Self::$variant)))*
- }
-
- fn syntax(&self) -> &SyntaxNode {
- match self {
- $(Self::$variant(node) => node.syntax(),)*
- }
- }
- }
-
- $(
- impl From<$variant> for $name {
- fn from(node: $variant) -> Self {
- Self::$variant(node)
- }
- }
- )*
- };
-}
-
-pub trait HasType: AstNode<Language = Lang> {
- fn type_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == TYPE)
- }
-}
-
-pub trait HasDelims: AstNode<Language = Lang> {
- fn left_delim_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == L_DELIM)
- }
-
- fn right_delim_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == R_DELIM)
- }
-}
-
-pub trait HasName: AstNode<Language = Lang> {
- fn name_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == NAME)
- }
-}
-
-pub trait HasEq: AstNode<Language = Lang> {
- fn eq_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == EQ)
- }
-}
-
-pub trait HasComma: AstNode<Language = Lang> {
- fn comma_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == COMMA)
- }
-}
-
-pub trait HasPound: AstNode<Language = Lang> {
- fn pound_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == POUND)
- }
-}
-
-pub trait HasInteger: AstNode<Language = Lang> {
- fn integer_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == INTEGER)
- }
-}
-
-pub trait HasCommandName: AstNode<Language = Lang> {
- fn command_name_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == COMMAND_NAME)
- }
-}
-
-pub trait HasAccentName: AstNode<Language = Lang> {
- fn accent_name_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == ACCENT_NAME)
- }
-}
-
-pub trait HasWord: AstNode<Language = Lang> {
- fn word_token(&self) -> Option<SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|token| token.kind() == WORD)
- }
-}
-
-pub trait HasValue: AstNode<Language = Lang> {
- fn value(&self) -> Option<Value> {
- self.syntax().children().find_map(Value::cast)
- }
-}
-
-ast_node!(name: Root, kinds: [ROOT], traits: []);
-
-impl Root {
- pub fn strings(&self) -> impl Iterator<Item = StringDef> {
- self.syntax().children().filter_map(StringDef::cast)
- }
-
- pub fn entries(&self) -> impl Iterator<Item = Entry> {
- self.syntax().children().filter_map(Entry::cast)
- }
-
- pub fn find_entry(&self, name: &str) -> Option<Entry> {
- self.entries().find(|entry| {
- entry
- .name_token()
- .map_or(false, |token| token.text() == name)
- })
- }
-}
-
-ast_node!(name: Preamble, kinds: [PREAMBLE], traits: [HasType, HasDelims, HasValue]);
-
-ast_node!(name: StringDef, kinds: [STRING], traits: [HasType, HasDelims, HasName, HasEq, HasValue]);
-
-ast_node!(name: Entry, kinds: [ENTRY], traits: [HasType, HasDelims, HasName, HasComma]);
-
-impl Entry {
- pub fn fields(&self) -> impl Iterator<Item = Field> {
- self.syntax().children().filter_map(Field::cast)
- }
-}
-
-ast_node!(name: Field, kinds: [FIELD], traits: [HasName, HasEq, HasValue, HasComma]);
-
-ast_node_enum!(name: Value, variants: [Literal, CurlyGroup, QuoteGroup, Join, Accent, Command]);
-
-ast_node!(name: Literal, kinds: [LITERAL], traits: [HasName, HasInteger]);
-
-ast_node!(name: CurlyGroup, kinds: [CURLY_GROUP], traits: []);
-
-ast_node!(name: QuoteGroup, kinds: [QUOTE_GROUP], traits: []);
-
-ast_node!(name: Join, kinds: [JOIN], traits: [HasPound]);
-
-impl Join {
- pub fn left_value(&self) -> Option<Value> {
- self.syntax().children().find_map(Value::cast)
- }
-
- pub fn right_value(&self) -> Option<Value> {
- self.syntax().children().filter_map(Value::cast).nth(1)
- }
-}
+pub type SyntaxNode = rowan::SyntaxNode<BibtexLanguage>;
-ast_node!(name: Accent, kinds: [ACCENT], traits: [HasAccentName, HasWord]);
+pub type SyntaxToken = rowan::SyntaxToken<BibtexLanguage>;
-ast_node!(name: Command, kinds: [COMMAND], traits: [HasCommandName]);
+pub type SyntaxElement = rowan::SyntaxElement<BibtexLanguage>;
diff --git a/support/texlab/crates/syntax/src/bibtex/cst.rs b/support/texlab/crates/syntax/src/bibtex/cst.rs
new file mode 100644
index 0000000000..eb67fdb0d7
--- /dev/null
+++ b/support/texlab/crates/syntax/src/bibtex/cst.rs
@@ -0,0 +1,244 @@
+use rowan::{ast::AstNode, NodeOrToken};
+
+use super::{
+ BibtexLanguage,
+ SyntaxKind::{self, *},
+ SyntaxNode, SyntaxToken,
+};
+
+macro_rules! cst_node {
+ (name: $name:ident, kinds: [$($kind:pat),+], traits: [$($trait: ident),*]) => {
+ #[derive(Clone)]
+ pub struct $name {
+ node: SyntaxNode,
+ }
+
+ impl AstNode for $name {
+ type Language = BibtexLanguage;
+
+ fn can_cast(kind: SyntaxKind) -> bool {
+ match kind {
+ $($kind => true,)+
+ _ => false,
+ }
+ }
+
+ fn cast(node: SyntaxNode) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ match node.kind() {
+ $($kind => Some(Self { node}),)+
+ _ => None,
+ }
+ }
+
+ fn syntax(&self) -> &SyntaxNode {
+ &self.node
+ }
+ }
+
+ $(
+ impl $trait for $name { }
+ )*
+ };
+}
+
+macro_rules! cst_node_enum {
+ (name: $name:ident, variants: [$($variant:ident),+]) => {
+ #[derive(Clone)]
+ pub enum $name {
+ $($variant($variant),)*
+ }
+
+ impl AstNode for $name {
+ type Language = BibtexLanguage;
+
+ fn can_cast(kind: SyntaxKind) -> bool {
+ false $(|| $variant::can_cast(kind))+
+ }
+
+ fn cast(node: SyntaxNode) -> Option<Self>
+ where
+ Self: Sized,
+ {
+ None $(.or_else(|| $variant::cast(node.clone()).map(Self::$variant)))*
+ }
+
+ fn syntax(&self) -> &SyntaxNode {
+ match self {
+ $(Self::$variant(node) => node.syntax(),)*
+ }
+ }
+ }
+
+ $(
+ impl From<$variant> for $name {
+ fn from(node: $variant) -> Self {
+ Self::$variant(node)
+ }
+ }
+ )*
+ };
+}
+
+pub trait HasType: AstNode<Language = BibtexLanguage> {
+ fn type_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == TYPE)
+ }
+}
+
+pub trait HasDelims: AstNode<Language = BibtexLanguage> {
+ fn left_delim_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == L_DELIM)
+ }
+
+ fn right_delim_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == R_DELIM)
+ }
+}
+
+pub trait HasName: AstNode<Language = BibtexLanguage> {
+ fn name_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == NAME)
+ }
+}
+
+pub trait HasEq: AstNode<Language = BibtexLanguage> {
+ fn eq_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == EQ)
+ }
+}
+
+pub trait HasComma: AstNode<Language = BibtexLanguage> {
+ fn comma_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == COMMA)
+ }
+}
+
+pub trait HasPound: AstNode<Language = BibtexLanguage> {
+ fn pound_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == POUND)
+ }
+}
+
+pub trait HasInteger: AstNode<Language = BibtexLanguage> {
+ fn integer_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == INTEGER)
+ }
+}
+
+pub trait HasCommandName: AstNode<Language = BibtexLanguage> {
+ fn command_name_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == COMMAND_NAME)
+ }
+}
+
+pub trait HasAccentName: AstNode<Language = BibtexLanguage> {
+ fn accent_name_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == ACCENT_NAME)
+ }
+}
+
+pub trait HasWord: AstNode<Language = BibtexLanguage> {
+ fn word_token(&self) -> Option<SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|token| token.kind() == WORD)
+ }
+}
+
+pub trait HasValue: AstNode<Language = BibtexLanguage> {
+ fn value(&self) -> Option<Value> {
+ self.syntax().children().find_map(Value::cast)
+ }
+}
+
+cst_node!(name: Root, kinds: [ROOT], traits: []);
+
+impl Root {
+ pub fn strings(&self) -> impl Iterator<Item = StringDef> {
+ self.syntax().children().filter_map(StringDef::cast)
+ }
+
+ pub fn entries(&self) -> impl Iterator<Item = Entry> {
+ self.syntax().children().filter_map(Entry::cast)
+ }
+
+ pub fn find_entry(&self, name: &str) -> Option<Entry> {
+ self.entries().find(|entry| {
+ entry
+ .name_token()
+ .map_or(false, |token| token.text() == name)
+ })
+ }
+}
+
+cst_node!(name: Preamble, kinds: [PREAMBLE], traits: [HasType, HasDelims, HasValue]);
+
+cst_node!(name: StringDef, kinds: [STRING], traits: [HasType, HasDelims, HasName, HasEq, HasValue]);
+
+cst_node!(name: Entry, kinds: [ENTRY], traits: [HasType, HasDelims, HasName, HasComma]);
+
+impl Entry {
+ pub fn fields(&self) -> impl Iterator<Item = Field> {
+ self.syntax().children().filter_map(Field::cast)
+ }
+}
+
+cst_node!(name: Field, kinds: [FIELD], traits: [HasName, HasEq, HasValue, HasComma]);
+
+cst_node_enum!(name: Value, variants: [Literal, CurlyGroup, QuoteGroup, Join, Accent, Command]);
+
+cst_node!(name: Literal, kinds: [LITERAL], traits: [HasName, HasInteger]);
+
+cst_node!(name: CurlyGroup, kinds: [CURLY_GROUP], traits: []);
+
+cst_node!(name: QuoteGroup, kinds: [QUOTE_GROUP], traits: []);
+
+cst_node!(name: Join, kinds: [JOIN], traits: [HasPound]);
+
+impl Join {
+ pub fn left_value(&self) -> Option<Value> {
+ self.syntax().children().find_map(Value::cast)
+ }
+
+ pub fn right_value(&self) -> Option<Value> {
+ self.syntax().children().filter_map(Value::cast).nth(1)
+ }
+}
+
+cst_node!(name: Accent, kinds: [ACCENT], traits: [HasAccentName, HasWord]);
+
+cst_node!(name: Command, kinds: [COMMAND], traits: [HasCommandName]);
diff --git a/support/texlab/crates/syntax/src/bibtex/kind.rs b/support/texlab/crates/syntax/src/bibtex/kind.rs
new file mode 100644
index 0000000000..7817f47495
--- /dev/null
+++ b/support/texlab/crates/syntax/src/bibtex/kind.rs
@@ -0,0 +1,43 @@
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
+#[allow(non_camel_case_types)]
+#[repr(u16)]
+pub enum SyntaxKind {
+ WHITESPACE,
+ JUNK,
+ L_DELIM,
+ R_DELIM,
+ L_CURLY,
+ R_CURLY,
+ COMMA,
+ POUND,
+ QUOTE,
+ EQ,
+ TYPE,
+ WORD,
+ NAME,
+ INTEGER,
+ NBSP,
+ ACCENT_NAME,
+ COMMAND_NAME,
+
+ PREAMBLE,
+ STRING,
+ ENTRY,
+ FIELD,
+ VALUE,
+ LITERAL,
+ JOIN,
+ ACCENT,
+ COMMAND,
+ CURLY_GROUP,
+ QUOTE_GROUP,
+ ROOT,
+}
+
+pub use SyntaxKind::*;
+
+impl From<SyntaxKind> for rowan::SyntaxKind {
+ fn from(kind: SyntaxKind) -> Self {
+ Self(kind as u16)
+ }
+}
diff --git a/support/texlab/crates/syntax/src/lib.rs b/support/texlab/crates/syntax/src/lib.rs
index c2c0552652..dc8761b73d 100644
--- a/support/texlab/crates/syntax/src/lib.rs
+++ b/support/texlab/crates/syntax/src/lib.rs
@@ -20,16 +20,3 @@ pub struct BuildError {
pub struct BuildLog {
pub errors: Vec<BuildError>,
}
-
-#[macro_export]
-macro_rules! match_ast {
- (match $node:ident { $($tt:tt)* }) => { $crate::match_ast!(match ($node) { $($tt)* }) };
-
- (match ($node:expr) {
- $( $( $path:ident )::+ ($it:pat) => $res:expr, )*
- _ => $catch_all:expr $(,)?
- }) => {{
- $( if let Some($it) = $($path::)+cast($node.clone()) { $res } else )*
- { $catch_all }
- }};
-}