Skip to content

Commit 6413df8

Browse files
Merge pull request #119 from lorenzwalthert/pr106_5_token_dep_ind
Re-indent token-dependent. #119
2 parents 7dd6965 + d6a71ed commit 6413df8

30 files changed

+1025
-69
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Collate:
4040
'nested.R'
4141
'nested_to_tree.R'
4242
'parsed.R'
43+
'reindent.R'
4344
'token.R'
4445
'relevel.R'
4546
'rules-line_break.R'

R/get_transformers.R

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,19 @@ get_transformers_nested <- function(
113113
)
114114

115115

116+
indention_modifier <-
117+
c(
118+
update_indention_ref_fun_dec,
119+
update_indention_ref_fun_call
120+
)
121+
116122
list(
117123
# transformer functions
118124
filler = create_filler,
119125
line_break = line_break_manipulators,
120126
space = space_manipulators,
121127
token = token_manipulators,
122-
128+
indention = indention_modifier,
123129
# transformer options
124130
use_raw_indention = use_raw_indention,
125131
NULL

R/parsed.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ create_filler <- function(pd_flat) {
9292
pd_flat$col2_nl <- if_else(pd_flat$newlines > 0L, 0L, pd_flat$col2)
9393
pd_flat$spaces <- pd_flat$col3 - pd_flat$col2_nl - 1L
9494
pd_flat$multi_line <- ifelse(pd_flat$terminal, FALSE, NA)
95-
95+
pd_flat$indention_ref_id <- NA
9696
ret <- pd_flat[, !(names(pd_flat) %in% c("line3", "col3", "col2_nl"))]
9797

9898

R/reindent.R

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
2+
#' Update the indention reference
3+
#'
4+
#' @param pd_nested A nested parse table.
5+
#' @name update_indention_ref
6+
NULL
7+
8+
9+
#' @describeIn update_indention_ref Updates the reference id for all
10+
#' tokens in `pd_nested` if `pd_nested` contains a function call. Tokens that
11+
#' start on the same line as the opening parenthesis, are not themselves
12+
#' function calls or expressions wrapped in curly brackets are re-indented,
13+
#' that is, they are indented up to the level at which the call ends in
14+
#' terms of col2. We need to take the last from the first child because calls
15+
#' like package::function() can have three elements.
16+
#' @examples
17+
#' \dontrun{
18+
#' # not re-indented
19+
#' call(call(
20+
#' xyz
21+
#' ))
22+
#' # re-indented
23+
#' call(call(1,
24+
#' 2))
25+
#' }
26+
#' @importFrom purrr map_lgl
27+
update_indention_ref_fun_call <- function(pd_nested) {
28+
current_is_call <- pd_nested$token_before[2] %in% c("SYMBOL_FUNCTION_CALL")
29+
non_comment <- which(pd_nested$token != "COMMENT")
30+
first_non_comment_after_call <- non_comment[non_comment > 2][1]
31+
if ((current_is_call) &&
32+
nrow(pd_nested) > 3 &&
33+
pd_nested$lag_newlines[first_non_comment_after_call] == 0) {
34+
candidates <- 3:(nrow(pd_nested) - 1)
35+
36+
child_is_call <- map_lgl(pd_nested$child, is_function_call)
37+
child_is_curly_expr <- map_lgl(pd_nested$child, is_curly_expr)
38+
child_is_on_same_line <- cumsum(pd_nested$lag_newlines) == 0
39+
call_on_same_line <- child_is_call & child_is_on_same_line
40+
to_indent <- setdiff(candidates, which(call_on_same_line | child_is_curly_expr))
41+
42+
pd_nested$indention_ref_id[to_indent] <- last(pd_nested$child[[1]]$id)
43+
}
44+
pd_nested
45+
}
46+
47+
#' @describeIn update_indention_ref Updates the reference id for all
48+
#' tokens in `pd_nested` if `pd_nested` contains a function declaration.
49+
#' Tokens inside a function declaration are are re-indented,
50+
#' that is, they are indented up to the level at which the token FUNCTION
51+
#' ends in terms of col2.
52+
#' @examples
53+
#' \dontrun{
54+
#' a <- function(x,
55+
#' y) {
56+
#' x + y
57+
#' }
58+
#' }
59+
update_indention_ref_fun_dec <- function(pd_nested) {
60+
if (pd_nested$token[1] == "FUNCTION" &&
61+
nrow(pd_nested) > 3) {
62+
seq <- 3:(nrow(pd_nested) - 1)
63+
pd_nested$indention_ref_id[seq] <- pd_nested$id[1]
64+
}
65+
pd_nested
66+
}
67+
68+
#' Check whether a parse table corresponds to a a certain expression
69+
#'
70+
#' @param pd A parse table.
71+
#' @name pd_is
72+
NULL
73+
74+
#' @describeIn pd_is Checks whether `pd` contains an expression wrapped in
75+
#' curley brackets.
76+
is_curly_expr <- function(pd) {
77+
if (is.null(pd)) return(FALSE)
78+
pd$token[1] == "'{'"
79+
}
80+
81+
#' @describeIn pd_is Checks whether `pd` is a function call.
82+
is_function_call <- function(pd) {
83+
if (is.null(pd)) return(FALSE)
84+
if (is.na(pd$token_before[2])) return(FALSE)
85+
pd$token_before[2] == "SYMBOL_FUNCTION_CALL"
86+
}
87+
88+
89+
#' Apply reference indention to tokens
90+
#'
91+
#' Applies the reference indention created with functions
92+
#' [update_indention_ref()] to the flattened parse table. The indention
93+
#' is applied to all token that inherit from a reference token sequentially,
94+
#' i.e. by looping over the target tokens.
95+
#' @inheritParams apply_ref_indention_one
96+
apply_ref_indention <- function(flattened_pd) {
97+
target_tokens <- which(flattened_pd$id %in% flattened_pd$indention_ref_id)
98+
flattened_pd <- reduce(
99+
target_tokens,
100+
apply_ref_indention_one,
101+
.init = flattened_pd
102+
)
103+
flattened_pd
104+
}
105+
106+
#' Applying reference indention of a target token
107+
#'
108+
#' Applies the indention level of `target_token` to all tokens that have
109+
#' `target_token` as a reference. This includes adding spaces to the first
110+
#' tokens on a line and updating the column `col1` and `col2` for all tokens
111+
#' on that line so they are kept updated.
112+
#' @param flattened_pd A flattened parse table
113+
#' @param target_token The index of the token from wich the indention level
114+
#' should be applied to other tokens.
115+
apply_ref_indention_one <- function(flattened_pd, target_token) {
116+
token_points_to_ref <-
117+
flattened_pd$indention_ref_id == flattened_pd$id[target_token]
118+
first_token_on_line <- flattened_pd$lag_newlines > 0L
119+
token_to_update <- which(token_points_to_ref & first_token_on_line)
120+
121+
# udate spaces
122+
copied_spaces <- flattened_pd$col2[target_token] + 1
123+
old_spaces <- flattened_pd$lag_spaces[token_to_update[1]]
124+
shift <- copied_spaces - old_spaces
125+
flattened_pd$lag_spaces[token_to_update] <-
126+
flattened_pd$lag_spaces[token_to_update] + shift
127+
128+
# update col1 / col2
129+
cols_to_update <- flattened_pd$line1 %in% flattened_pd$line1[token_to_update]
130+
flattened_pd$col1[cols_to_update] <- flattened_pd$col1[cols_to_update] + shift
131+
flattened_pd$col2[cols_to_update] <- flattened_pd$col2[cols_to_update] + shift
132+
flattened_pd
133+
134+
}

R/rules-spacing.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ set_space_after_comma <- function(pd_flat) {
105105
}
106106

107107
remove_space_before_comma <- function(pd_flat) {
108-
comma_after <- (pd_flat$token == "','") & (pd_flat$newlines == 0L)
108+
comma_after <- pd_flat$token == "','"
109109
if (!any(comma_after)) return(pd_flat)
110110
comma_before <- lead(comma_after, default = FALSE)
111111
idx <- comma_before & (pd_flat$newlines == 0L)

R/transform.R

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ parse_transform_serialize <- function(text, transformers) {
8686
transformed_pd <- apply_transformers(pd_nested, transformers)
8787
# TODO verify_roundtrip
8888
flattened_pd <- post_visit(transformed_pd, list(extract_terminals)) %>%
89-
enrich_terminals(transformers$use_raw_indention)
89+
enrich_terminals(transformers$use_raw_indention) %>%
90+
apply_ref_indention()
9091

9192
serialized_transformed_text <- serialize_parse_data_flattened(flattened_pd)
9293
serialized_transformed_text
@@ -119,14 +120,15 @@ apply_transformers <- function(pd_nested, transformers) {
119120

120121
transformed_all <- pre_visit(
121122
transformed_updated_multi_line,
122-
c(transformers$space, transformers$token)
123+
c(transformers$space, transformers$token, transformers$indention)
123124
)
124125

125126
transformed_absolute_indent <- context_to_terminals(
126127
transformed_all,
127128
outer_lag_newlines = 0,
128129
outer_indent = 0,
129-
outer_spaces = 0
130+
outer_spaces = 0,
131+
outer_indention_refs = NA
130132
)
131133

132134
transformed_absolute_indent

R/visit.R

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,20 @@ visit_one <- function(pd_flat, funs) {
5656
context_to_terminals <- function(pd_nested,
5757
outer_lag_newlines,
5858
outer_indent,
59-
outer_spaces) {
59+
outer_spaces,
60+
outer_indention_refs) {
6061

6162
if (is.null(pd_nested)) return()
6263

6364
pd_transformed <- context_towards_terminals(
64-
pd_nested, outer_lag_newlines, outer_indent, outer_spaces
65+
pd_nested, outer_lag_newlines, outer_indent, outer_spaces, outer_indention_refs
6566
)
6667

6768
pd_transformed$child <- pmap(list(pd_transformed$child,
6869
pd_transformed$lag_newlines,
6970
pd_transformed$indent,
70-
pd_transformed$spaces),
71+
pd_transformed$spaces,
72+
pd_transformed$indention_ref_id),
7173
context_to_terminals)
7274
pd_transformed
7375
}
@@ -84,13 +86,18 @@ context_to_terminals <- function(pd_nested,
8486
#' @param outer_lag_newlines The lag_newlines to be propagated inwards.
8587
#' @param outer_indent The indention depth to be propagated inwards.
8688
#' @param outer_spaces The number of spaces to be propagated inwards.
89+
#' @param outer_indention_refs The reference id that should be propagated
90+
#' inwards.
8791
#' @return An updated parse table.
8892
#' @seealso context_to_terminals
8993
context_towards_terminals <- function(pd_nested,
9094
outer_lag_newlines,
9195
outer_indent,
92-
outer_spaces) {
96+
outer_spaces,
97+
outer_indention_refs) {
9398
pd_nested$indent <- pd_nested$indent + outer_indent
99+
ref_id_is_na <- !is.na(pd_nested$indention_ref_id)
100+
pd_nested$indention_ref_id[!ref_id_is_na] <- outer_indention_refs
94101
pd_nested$lag_newlines[1] <- pd_nested$lag_newlines[1] + outer_lag_newlines
95102
pd_nested$spaces[nrow(pd_nested)] <-
96103
pd_nested$spaces[nrow(pd_nested)] + outer_spaces
@@ -119,10 +126,15 @@ extract_terminals <- function(pd_nested) {
119126
#' which the token starts. `line1` has the same meaning as `line1` that can be
120127
#' found in a flat parse table (see [tokenize()]), just that the `line1`
121128
#' created by `enrich_terminals()` is the updated version of the former
122-
#' `line1`. The same applies for `col1` and `col2`.
129+
#' `line1`. The same applies for `col1` and `col2`. Note that this function
130+
#' does remove the columns `indent` and `spaces.` All information of the former
131+
#' is stored in `lag_spaces` now. The later was removed because it is redundant
132+
#' after adding the column `lag_spaces`, which is more convenient to work with,
133+
#' in particular when serializing the parse table.
123134
#' @inheritParams choose_indention
124135
enrich_terminals <- function(flattened_pd, use_raw_indention = FALSE) {
125136
flattened_pd$lag_spaces <- lag(flattened_pd$spaces, default = 0L)
137+
flattened_pd$spaces <- NULL # depreciate spaces
126138
flattened_pd <- choose_indention(flattened_pd, use_raw_indention)
127139
flattened_pd$line1 <-
128140
cumsum(flattened_pd$lag_newlines) + flattened_pd$line1[1]

man/apply_ref_indention.Rd

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/apply_ref_indention_one.Rd

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/context_to_terminals.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/context_towards_terminals.Rd

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/enrich_terminals.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/pd_is.Rd

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)