Two helper functions
- First, we need an
epxr_type()
function to return the type of expression element as a string.
expr_type <- function(x) {
if (rlang::is_syntactic_literal(x)) {
"constant"
} else if (is.symbol(x)) {
"symbol"
} else if (is.call(x)) {
"call"
} else if (is.pairlist(x)) {
"pairlist"
} else {
typeof(x)
}
}
expr_type(expr("a"))
# [1] "constant"
expr_type(expr(x))
# [1] "symbol"
expr_type(expr(f(1, 2)))
# [1] "call"
- Second, we need a wrapper function to handle exceptions.
switch_expr <- function(x, ...) {
switch(expr_type(x),
...,
stop("Don't know how to handle type ", typeof(x), call. = FALSE)
)
}
- Lastly, we can write a basic template that walks the AST using the
switch()
statement.
recurse_call <- function(x) {
switch_expr(x,
# Base cases
symbol = ,
constant = ,
# Recursive cases
call = ,
pairlist =
)
}