This commit is contained in:
Aleksey Kladov 2018-08-11 12:28:59 +03:00
parent d5119133fc
commit 7afd84febc
11 changed files with 211 additions and 86 deletions

View file

@ -1,4 +1,5 @@
pub mod walk;
pub mod visit;
use {SyntaxNodeRef, TextUnit, TextRange};

View file

@ -0,0 +1,52 @@
use std::marker::PhantomData;
use {SyntaxNodeRef, AstNode, SyntaxRoot};
pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> {
EmptyVisitor { ph: PhantomData }
}
pub trait Visitor<'a>: Sized {
type Output;
fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>;
fn visit<N, F>(self, f: F) -> Vis<Self, N, F>
where N: AstNode<&'a SyntaxRoot>,
F: FnOnce(N) -> Self::Output,
{
Vis { inner: self, f, ph: PhantomData }
}
}
#[derive(Debug)]
struct EmptyVisitor<T> {
ph: PhantomData<fn() -> T>
}
impl<'a, T> Visitor<'a> for EmptyVisitor<T> {
type Output = T;
fn accept(self, _node: SyntaxNodeRef<'a>) -> Option<T> {
None
}
}
#[derive(Debug)]
pub struct Vis<V, N, F> {
inner: V,
f: F,
ph: PhantomData<fn(N)>,
}
impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F>
where
V: Visitor<'a>,
N: AstNode<&'a SyntaxRoot>,
F: FnOnce(N) -> <V as Visitor<'a>>::Output,
{
type Output = <V as Visitor<'a>>::Output;
fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output> {
let Vis { inner, f, .. } = self;
inner.accept(node).or_else(|| N::cast(node).map(f))
}
}

View file

@ -1,9 +1,11 @@
use std::sync::Arc;
use {
ast,
SyntaxNode, SyntaxRoot, TreeRoot, AstNode,
SyntaxKind::*,
};
// ConstItem
#[derive(Debug, Clone, Copy)]
pub struct ConstItem<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -19,15 +21,10 @@ impl<R: TreeRoot> AstNode<R> for ConstItem<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> ConstItem<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for ConstItem<R> {}
impl<R: TreeRoot> ConstItem<R> {}
// Enum
#[derive(Debug, Clone, Copy)]
pub struct Enum<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -43,15 +40,10 @@ impl<R: TreeRoot> AstNode<R> for Enum<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> Enum<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for Enum<R> {}
impl<R: TreeRoot> Enum<R> {}
// File
#[derive(Debug, Clone, Copy)]
pub struct File<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -75,6 +67,7 @@ impl<R: TreeRoot> File<R> {
}
}
// Function
#[derive(Debug, Clone, Copy)]
pub struct Function<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -90,15 +83,10 @@ impl<R: TreeRoot> AstNode<R> for Function<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> Function<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for Function<R> {}
impl<R: TreeRoot> Function<R> {}
// Module
#[derive(Debug, Clone, Copy)]
pub struct Module<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -114,15 +102,10 @@ impl<R: TreeRoot> AstNode<R> for Module<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> Module<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for Module<R> {}
impl<R: TreeRoot> Module<R> {}
// Name
#[derive(Debug, Clone, Copy)]
pub struct Name<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -140,6 +123,7 @@ impl<R: TreeRoot> AstNode<R> for Name<R> {
impl<R: TreeRoot> Name<R> {}
// StaticItem
#[derive(Debug, Clone, Copy)]
pub struct StaticItem<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -155,15 +139,10 @@ impl<R: TreeRoot> AstNode<R> for StaticItem<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> StaticItem<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for StaticItem<R> {}
impl<R: TreeRoot> StaticItem<R> {}
// Struct
#[derive(Debug, Clone, Copy)]
pub struct Struct<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -179,15 +158,10 @@ impl<R: TreeRoot> AstNode<R> for Struct<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> Struct<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for Struct<R> {}
impl<R: TreeRoot> Struct<R> {}
// Trait
#[derive(Debug, Clone, Copy)]
pub struct Trait<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -203,12 +177,6 @@ impl<R: TreeRoot> AstNode<R> for Trait<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
impl<R: TreeRoot> Trait<R> {
pub fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl<R: TreeRoot> ast::NameOwner<R> for Trait<R> {}
impl<R: TreeRoot> Trait<R> {}

View file

@ -1,9 +1,11 @@
use std::sync::Arc;
use {
ast,
SyntaxNode, SyntaxRoot, TreeRoot, AstNode,
SyntaxKind::*,
};
{% for node, methods in ast %}
// {{ node }}
#[derive(Debug, Clone, Copy)]
pub struct {{ node }}<R: TreeRoot = Arc<SyntaxRoot>> {
syntax: SyntaxNode<R>,
@ -19,6 +21,12 @@ impl<R: TreeRoot> AstNode<R> for {{ node }}<R> {
fn syntax(&self) -> &SyntaxNode<R> { &self.syntax }
}
{% if methods.traits -%}
{%- for t in methods.traits -%}
impl<R: TreeRoot> ast::{{ t }}<R> for {{ node }}<R> {}
{% endfor -%}
{%- endif -%}
impl<R: TreeRoot> {{ node }}<R> {
{%- if methods.collections -%}
{%- for m in methods.collections -%}

View file

@ -12,6 +12,15 @@ pub trait AstNode<R: TreeRoot>: Sized {
fn syntax(&self) -> &SyntaxNode<R>;
}
pub trait NameOwner<R: TreeRoot>: AstNode<R> {
fn name(&self) -> Option<Name<R>> {
self.syntax()
.children()
.filter_map(Name::cast)
.next()
}
}
impl File<Arc<SyntaxRoot>> {
pub fn parse(text: &str) -> Self {
File::cast(::parse(text)).unwrap()

View file

@ -220,39 +220,25 @@ Grammar(
]
),
"Function": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"Struct": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"Enum": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"Trait": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"Module": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"ConstItem": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"StaticItem": (
options: [
["name", "Name"]
]
traits: ["NameOwner"]
),
"Name": (),
},

View file

@ -28,6 +28,12 @@ impl<R: TreeRoot> Eq for SyntaxNode<R> {}
pub type SyntaxNodeRef<'a> = SyntaxNode<&'a SyntaxRoot>;
#[test]
fn syntax_node_ref_is_copy() {
fn assert_copy<T: Copy>(){}
assert_copy::<SyntaxNodeRef>()
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct SyntaxError {
pub msg: String,