Parsing mfunctions with mtree

62 views (last 30 days)
Matt J
Matt J on 15 Feb 2026 at 19:05
Commented: Rik on 20 Feb 2026 at 11:46
Given an Nx1 colum vector of strings containing lines of mfunction code, it is possible to use the undocumented function mtree() to parse it into its constituent functions. For example, given,
load Inputs
str1,
str1 = 17×1 string array
"function func1(x,y)" " " " disp(x) " " disp(y) " " " "end " " " "function func2(z) " " " " " "end " " " "function func3(z) " " " " disp(z) " " " "end "
the function below will find the starting and ending lines of each of the three function blocks.
[firstLine,lastLine] = functionBlocks(str1)
firstLine = 1×3
1 8 13
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
lastLine = 1×3
6 11 17
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
This works for nested functions as well:
str2,
str2 = 20×1 string array
"function func1(x,y) " " " " disp(x) " " disp(y) " " " "end " " " "function func2(z) " " " " " " " " function func3(z)" " " " disp(z) " " " " end " " " "end " " " " "
[firstLine,lastLine] = functionBlocks(str2)
firstLine = 1×3
1 8 12
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
lastLine = 1×3
6 18 16
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
However, I would really like to have the function be able to group the output separately into top-level function blocks and nested function blocks. I know it is possible to do this through a post-analysis of the outputs firstLine and lastLine, but I wonder if it is possible to get information about whether a function block is top-level or nested directly from mtree, i.e., by modifying,
fnSet = T.mtfind('Kind','FUNCTION');
Unfortunately, because mtree() is undocumented, it is difficult to fathom its full capabilities. Does anyone know if/how this can be done?
function [firstLine,lastLine] = functionBlocks(str)
T = mtree(strjoin(str,newline));
fnSet = T.mtfind('Kind','FUNCTION');
K=fnSet.count;
kset=fnSet.indices;
for k = K:-1:1
fn = fnSet.select(kset(k));
firstLine(k) = fn.lineno;
lastLine(k) = fn.lastone;
end
end
  1 Comment
Rik
Rik on 19 Feb 2026 at 9:59
I remember headaches like this when I wrote minify. It looks like writing a bit of boiler plate code for mtree is more efficient, but I am always hesitant to heavily rely on undocumented options. You could have a look to see if my code is useful to you.

Sign in to comment.

Answers (1)

Tridib
Tridib on 20 Feb 2026 at 5:39
Dear @Matt J,
I understand you want to enhance your "mtree"-based parsing so you can automatically separate MATLAB function blocks into top‑level and nested groups. Here are the steps that will lead you to that outcome:
  1. First convert your input into a single source string so the syntax tree is built consistently, while also keeping individual lines available so you can map line numbers back later.
  2. Build the mtree for that source and locate all the FUNCTION nodes, then record each node’s starting and ending line numbers and sort them by starting line so that the structure is easier to reason about.
  3. Check whether your version of mtree exposes a parent link. If so, classify a function as nested when its parent node is itself a FUNCTION, otherwise treat it as top‑level.
  4. If parent information is not available, fall back to a simple span‑based rule, a function is nested if its starting line falls within the line range of any earlier function.
  5. Once you know which are nested and which are top‑level, determine each function’s nearest parent by finding the smallest enclosing range and compute the nesting level by incrementing from the parent.
  6. Use these masks to separate your start/end line ranges cleanly into “top‑level” and “nested” groups, keeping them in source order so the grouping is intuitive.
  7. If you need names, extract them directly from the corresponding source lines using a tolerant pattern, but keep the structural logic strictly based on line numbers.
  8. Validate your approach on simple cases first, files with only top‑level functions, then files with one nested function, then deeper nesting, so you see your masks, parents, and levels behaving correctly.
  9. If helpful, build a higher‑level grouping where each top‑level function is paired with all its descendants so you can easily inspect the hierarchy or display it.
Hope this helps!
  1 Comment
Rik
Rik on 20 Feb 2026 at 11:46
Before letting some GenAI tool write the answer, perhaps you should have a look at the question.
You are personally responsible for what you post, good or bad. Did you check to see whether this question actually answers the question? Why didn't you at least implement the analyzer code that determines whether a function is a nested function?

Sign in to comment.

Products


Release

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!