Fix parser for index and call exprs, remove old test that didn't work, add visitor pattern
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
306
src/syn/ast.rs
306
src/syn/ast.rs
@@ -1,17 +1,125 @@
|
|||||||
|
use crate::syn::visit::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Expr(Expr),
|
Expr(Expr),
|
||||||
Assign,
|
Assign(AssignStmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for Stmt
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for Stmt {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_stmt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for Stmt
|
||||||
|
//
|
||||||
|
impl<V: Visit> DefaultAccept<V> for Stmt {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
match self {
|
||||||
|
Stmt::Expr(e) => e.accept(visitor),
|
||||||
|
Stmt::Assign(a) => a.accept(visitor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct AssignStmt {
|
||||||
|
pub lhs: LhsExpr,
|
||||||
|
pub rhs: Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for AssignStmt
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for AssignStmt {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_assign_stmt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for AssignStmt
|
||||||
|
//
|
||||||
|
impl<V: Visit<Out=()>> DefaultAccept<V> for AssignStmt {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
self.lhs.accept(visitor);
|
||||||
|
self.rhs.accept(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum LhsExpr {
|
||||||
|
SetAttr(AccessExpr),
|
||||||
|
Local(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for LhsExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for LhsExpr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_lhs_expr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for LhsExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit<Out=()>> DefaultAccept<V> for LhsExpr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
match self {
|
||||||
|
LhsExpr::SetAttr(a) => a.accept(visitor),
|
||||||
|
LhsExpr::Local(_) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct Expr
|
||||||
|
//
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
Bin(Box<BinExpr>),
|
Bin(Box<BinExpr>),
|
||||||
Un(Box<UnExpr>),
|
Un(Box<UnExpr>),
|
||||||
Access(Box<AccessExpr>),
|
Access(Box<AccessExpr>),
|
||||||
|
Call(Box<CallExpr>),
|
||||||
|
Index(Box<IndexExpr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for Expr
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for Expr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_expr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for Expr
|
||||||
|
//
|
||||||
|
impl<V: Visit> DefaultAccept<V> for Expr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
match self {
|
||||||
|
Expr::Atom(a) => a.accept(visitor),
|
||||||
|
Expr::Bin(b) => b.accept(visitor),
|
||||||
|
Expr::Un(u) => u.accept(visitor),
|
||||||
|
Expr::Access(a) => a.accept(visitor),
|
||||||
|
Expr::Call(c) => c.accept(visitor),
|
||||||
|
Expr::Index(i) => i.accept(visitor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl From<T> for Expr
|
||||||
|
//
|
||||||
impl From<Atom> for Expr {
|
impl From<Atom> for Expr {
|
||||||
fn from(other: Atom) -> Self {
|
fn from(other: Atom) -> Self {
|
||||||
Expr::Atom(other)
|
Expr::Atom(other)
|
||||||
@@ -36,6 +144,18 @@ impl From<AccessExpr> for Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<CallExpr> for Expr {
|
||||||
|
fn from(other: CallExpr) -> Self {
|
||||||
|
Expr::Call(other.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IndexExpr> for Expr {
|
||||||
|
fn from(other: IndexExpr) -> Self {
|
||||||
|
Expr::Index(other.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
Plus,
|
Plus,
|
||||||
@@ -52,6 +172,9 @@ pub enum BinOp {
|
|||||||
Or,
|
Or,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct BinExpr
|
||||||
|
//
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct BinExpr {
|
pub struct BinExpr {
|
||||||
pub lhs: Expr,
|
pub lhs: Expr,
|
||||||
@@ -65,12 +188,34 @@ impl BinExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for BinExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for BinExpr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_bin_expr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for BinExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit<Out=()>> DefaultAccept<V> for BinExpr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_expr(&self.lhs);
|
||||||
|
visitor.visit_expr(&self.rhs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct UnExpr
|
||||||
|
//
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct UnExpr {
|
pub struct UnExpr {
|
||||||
pub op: UnOp,
|
pub op: UnOp,
|
||||||
@@ -83,28 +228,124 @@ impl UnExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for UnExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for UnExpr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_un_expr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for UnExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit> DefaultAccept<V> for UnExpr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_expr(&self.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct CallExpr
|
||||||
|
//
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct CallExpr {
|
||||||
|
pub expr: Expr,
|
||||||
|
pub args: Vec<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CallExpr {
|
||||||
|
pub fn new_expr(expr: Expr, args: Vec<Expr>) -> Expr {
|
||||||
|
Self { expr, args }.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for CallExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for CallExpr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_call_expr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for CallExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit<Out=()>> DefaultAccept<V> for CallExpr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_expr(&self.expr);
|
||||||
|
self.args.iter()
|
||||||
|
.for_each(|arg| visitor.visit_expr(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct IndexExpr
|
||||||
|
//
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct IndexExpr {
|
||||||
|
pub expr: Expr,
|
||||||
|
pub index: Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexExpr {
|
||||||
|
pub fn new_expr(expr: Expr, index: Expr) -> Expr {
|
||||||
|
Self { expr, index, }.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for IndexExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit> Accept<V> for IndexExpr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_index_expr(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for IndexExpr
|
||||||
|
//
|
||||||
|
impl<V: Visit<Out=()>> DefaultAccept<V> for IndexExpr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_expr(&self.expr);
|
||||||
|
visitor.visit_expr(&self.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// struct AccessExpr
|
||||||
|
//
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct AccessExpr {
|
pub struct AccessExpr {
|
||||||
pub expr: Expr,
|
pub expr: Expr,
|
||||||
pub access: Vec<Access>,
|
pub access: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccessExpr {
|
impl AccessExpr {
|
||||||
pub fn new_expr(expr: Expr, access: Vec<Access>) -> Expr {
|
pub fn new_expr(expr: Expr, access: String) -> Expr {
|
||||||
Self { expr, access, }.into()
|
Self { expr, access, }.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
//
|
||||||
pub struct Access {
|
// impl Accept for AccessExpr
|
||||||
pub access: String,
|
//
|
||||||
pub trailing: Vec<ExprTrail>,
|
impl<V: Visit> Accept<V> for AccessExpr {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_access_expr(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
//
|
||||||
pub enum ExprTrail {
|
// impl DefaultAccept for AccessExpr
|
||||||
Call(Vec<Expr>),
|
//
|
||||||
Index(Expr),
|
impl<V: Visit> DefaultAccept<V> for AccessExpr {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_expr(&self.expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@@ -115,6 +356,16 @@ pub enum Atom {
|
|||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<V: Visit> Accept<V> for Atom {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
|
visitor.visit_atom(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: Visit<Out=()>> DefaultAccept<V> for Atom {
|
||||||
|
fn default_accept(&self, _visitor: &mut V) -> V::Out { }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<String>> {
|
pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<String>> {
|
||||||
use crate::syn::{lexer, parser};
|
use crate::syn::{lexer, parser};
|
||||||
let lexerdef = lexer::lexerdef();
|
let lexerdef = lexer::lexerdef();
|
||||||
@@ -129,36 +380,3 @@ pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<String>> {
|
|||||||
|
|
||||||
Ok(res.transpose().unwrap())
|
Ok(res.transpose().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
fn parse_expr(text: &str) -> Expr {
|
|
||||||
let mut body = parse(text)
|
|
||||||
.unwrap()
|
|
||||||
.unwrap();
|
|
||||||
assert!(body.len() == 1);
|
|
||||||
let stmt = body.pop().unwrap();
|
|
||||||
|
|
||||||
if let Stmt::Expr(expr) = stmt {
|
|
||||||
expr
|
|
||||||
} else {
|
|
||||||
panic!("{:?} parses to {:?} which is not a Stmt::Expr", text, stmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn access() {
|
|
||||||
assert_eq!(
|
|
||||||
parse_expr("a.b.c()"),
|
|
||||||
AccessExpr::new_expr(
|
|
||||||
Atom::Ident("a".to_string()).into(),
|
|
||||||
vec![
|
|
||||||
Access { access: "b".to_string(), trailing: vec![], },
|
|
||||||
Access { access: "c".to_string(), trailing: vec![ExprTrail::Call(vec![])], },
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
[0-9]+ "NUM"
|
[0-9]+ "NUM"
|
||||||
"([^"]|\\[rnt"'\\])+"|'([^"]|\\[rnt"'\\])+' "STRING"
|
"([^"]|\\[rnt"'\\])+"|'([^"]|\\[rnt"'\\])+' "STRING"
|
||||||
|
|
||||||
|
= "="
|
||||||
\|\| "||"
|
\|\| "||"
|
||||||
&& "&&"
|
&& "&&"
|
||||||
< "<"
|
< "<"
|
||||||
|
|||||||
10
src/syn/macros.rs
Normal file
10
src/syn/macros.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#[macro_export]
|
||||||
|
macro_rules! accept_default {
|
||||||
|
($visitor:ty, $acceptor:ty) => {
|
||||||
|
impl $crate::syn::visit::Accept for $acceptor<$visitor> {
|
||||||
|
fn accept(&self, visitor: &mut $visitor) -> $visitor::Out {
|
||||||
|
$crate::syn::visit::DefaultAccept::default_accept(self, visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
|
#![macro_use] mod macros;
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
|
pub mod visit;
|
||||||
|
|
||||||
pub mod lexer {
|
pub mod lexer {
|
||||||
lrlex_mod!("syn/lexer.l");
|
lrlex_mod!("syn/lexer.l");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ Body -> Result<Vec<Stmt>>:
|
|||||||
|
|
||||||
Stmt -> Result<Stmt>:
|
Stmt -> Result<Stmt>:
|
||||||
Expr { Ok(Stmt::Expr($1?)) }
|
Expr { Ok(Stmt::Expr($1?)) }
|
||||||
|
//| Assign { todo!() }
|
||||||
;
|
;
|
||||||
|
|
||||||
Expr -> Result<Expr>: BinExpr { $1 };
|
Expr -> Result<Expr>: BinExpr { $1 };
|
||||||
@@ -42,31 +43,24 @@ BinExpr -> Result<Expr>:
|
|||||||
UnExpr -> Result<Expr>:
|
UnExpr -> Result<Expr>:
|
||||||
'+' UnExpr { Ok(UnExpr::new_expr(UnOp::Plus, $2?)) }
|
'+' UnExpr { Ok(UnExpr::new_expr(UnOp::Plus, $2?)) }
|
||||||
| '-' UnExpr { Ok(UnExpr::new_expr(UnOp::Minus, $2?)) }
|
| '-' UnExpr { Ok(UnExpr::new_expr(UnOp::Minus, $2?)) }
|
||||||
|
| CallIndexExpr { $1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
// TODO - add CallExpr and IndexExpr, allow them to nest
|
||||||
|
// - UnExpr will point to CallIndexExpr
|
||||||
|
// - Call/Index exprs are based on an AccessExpr
|
||||||
|
// - AccessExpr will retain ExprTrailing in between its items, but should end in a .ident
|
||||||
|
|
||||||
|
CallIndexExpr -> Result<Expr>:
|
||||||
|
IndexExpr { $1 }
|
||||||
|
| CallExpr { $1 }
|
||||||
| AccessExpr { $1 }
|
| AccessExpr { $1 }
|
||||||
;
|
;
|
||||||
|
|
||||||
AccessExpr -> Result<Expr>:
|
CallExpr -> Result<Expr>:
|
||||||
AtomExpr AccessExprTail {
|
CallIndexExpr '(' FunArgs ')' {
|
||||||
Ok(AccessExpr::new_expr($1?, $2?))
|
Ok(CallExpr::new_expr($1?, $3?))
|
||||||
}
|
}
|
||||||
| AtomExpr {
|
|
||||||
Ok(AccessExpr::new_expr($1?, Default::default()))
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
AccessExprTail -> Result<Vec<Access>>:
|
|
||||||
AccessExprTail '.' Ident ExprTrailing {
|
|
||||||
flatten($1, Ok(Access { access: $3?, trailing: $4? }))
|
|
||||||
}
|
|
||||||
| '.' Ident ExprTrailing {
|
|
||||||
Ok(vec![Access { access: $2?, trailing: $3? }])
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
ExprTrailing -> Result<Vec<ExprTrail>>:
|
|
||||||
ExprTrailing '(' FunArgs ')' { flatten($1, Ok(ExprTrail::Call($3?))) }
|
|
||||||
| ExprTrailing '[' Expr ']' { flatten($1, Ok(ExprTrail::Index($3?))) }
|
|
||||||
| { Ok(Vec::new()) }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
FunArgs -> Result<Vec<Expr>>:
|
FunArgs -> Result<Vec<Expr>>:
|
||||||
@@ -79,6 +73,17 @@ FunArgsTail -> Result<Vec<Expr>>:
|
|||||||
| Expr { Ok(vec![$1?]) }
|
| Expr { Ok(vec![$1?]) }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
IndexExpr -> Result<Expr>:
|
||||||
|
CallIndexExpr '[' Expr ']' {
|
||||||
|
Ok(IndexExpr::new_expr($1?, $3?))
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
AccessExpr -> Result<Expr>:
|
||||||
|
AtomExpr { $1 }
|
||||||
|
| CallIndexExpr '.' Ident { Ok(AccessExpr::new_expr($1?, $3?)) }
|
||||||
|
;
|
||||||
|
|
||||||
AtomExpr -> Result<Expr>:
|
AtomExpr -> Result<Expr>:
|
||||||
Atom { $1.map(Expr::Atom) }
|
Atom { $1.map(Expr::Atom) }
|
||||||
| '(' Expr ')' { $2 }
|
| '(' Expr ')' { $2 }
|
||||||
|
|||||||
24
src/syn/visit.rs
Normal file
24
src/syn/visit.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
use crate::syn::ast::*;
|
||||||
|
|
||||||
|
pub trait Accept<V: Visit + ?Sized> {
|
||||||
|
fn accept(&self, visitor: &mut V) -> V::Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DefaultAccept<V: Visit + ?Sized> {
|
||||||
|
fn default_accept(&self, visitor: &mut V) -> V::Out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Visit {
|
||||||
|
type Out;
|
||||||
|
|
||||||
|
fn visit_stmt(&mut self, stmt: &Stmt) -> Self::Out;
|
||||||
|
fn visit_assign_stmt(&mut self, assign: &AssignStmt) -> Self::Out;
|
||||||
|
fn visit_lhs_expr(&mut self, lhs_expr: &LhsExpr) -> Self::Out;
|
||||||
|
fn visit_expr(&mut self, expr: &Expr) -> Self::Out;
|
||||||
|
fn visit_bin_expr(&mut self, expr: &BinExpr) -> Self::Out;
|
||||||
|
fn visit_un_expr(&mut self, expr: &UnExpr) -> Self::Out;
|
||||||
|
fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out;
|
||||||
|
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out;
|
||||||
|
fn visit_access_expr(&mut self, expr: &AccessExpr) -> Self::Out;
|
||||||
|
fn visit_atom(&mut self, atom: &Atom) -> Self::Out;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user