MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ parse()

static KernelSource MayaFlux::Portal::Graphics::KernelSource::parse ( std::string_view  stringified)
inlinestatic

Parse parameter names and body from a stringified lambda.

Extracts identifiers from the parameter list by stripping type tokens (everything up to and including the last space or * before the identifier). Extracts body as the text between the first { and the matching closing }.

Parameters
stringifiedRaw text produced by MF_KERNEL.
Returns
Populated KernelSource.

< Locate parameter list: between first '(' after '[' and its matching ')'

< points at the closing ')'

< Split on ',' and extract the last token (the identifier) from each param

< strip trailing whitespace

< find last space or * - identifier follows

< find next comma not inside <> or ()

Definition at line 73 of file ShaderSpec.hpp.

74 {
75 KernelSource ks;
76 ks.raw = std::string(stringified);
77
78 ///< Locate parameter list: between first '(' after '[' and its matching ')'
79 const auto bracket = stringified.find('[');
80 const auto paren_open = stringified.find('(', bracket);
81 if (paren_open == std::string_view::npos)
82 return ks;
83
84 std::size_t depth = 1;
85 std::size_t paren_close = paren_open + 1;
86 while (paren_close < stringified.size() && depth > 0) {
87 if (stringified[paren_close] == '(') {
88 ++depth;
89 } else if (stringified[paren_close] == ')') {
90 --depth;
91 }
92 ++paren_close;
93 }
94 --paren_close; ///< points at the closing ')'
95
96 const auto params_text = stringified.substr(paren_open + 1, paren_close - paren_open - 1);
97
98 ///< Split on ',' and extract the last token (the identifier) from each param
99 auto extract_name = [](std::string_view param) -> std::string {
100 ///< strip trailing whitespace
101 auto end = param.find_last_not_of(" \t\n\r");
102 if (end == std::string_view::npos)
103 return {};
104 param = param.substr(0, end + 1);
105 ///< find last space or * - identifier follows
106 auto sep = param.find_last_of(" *\t");
107 if (sep == std::string_view::npos)
108 return std::string(param);
109 return std::string(param.substr(sep + 1));
110 };
111
112 std::size_t start = 0;
113 while (start < params_text.size()) {
114 ///< find next comma not inside <> or ()
115 int angle = 0, paren = 0;
116 std::size_t pos = start;
117 while (pos < params_text.size()) {
118 char c = params_text[pos];
119 if (c == '<') {
120 ++angle;
121 } else if (c == '>') {
122 --angle;
123 } else if (c == '(') {
124 ++paren;
125 } else if (c == ')') {
126 --paren;
127 } else if (c == ',' && angle == 0 && paren == 0) {
128 break;
129 }
130 ++pos;
131 }
132 auto name = extract_name(params_text.substr(start, pos - start));
133 if (!name.empty())
134 ks.param_names.push_back(std::move(name));
135 start = (pos < params_text.size()) ? pos + 1 : pos;
136 }
137
138 ///< Locate body: between first '{' after ')' and its matching '}'
139 const auto brace_open = stringified.find('{', paren_close);
140 if (brace_open == std::string_view::npos)
141 return ks;
142
143 depth = 1;
144 std::size_t brace_close = brace_open + 1;
145 while (brace_close < stringified.size() && depth > 0) {
146 if (stringified[brace_close] == '{') {
147 ++depth;
148 } else if (stringified[brace_close] == '}') {
149 --depth;
150 }
151 ++brace_close;
152 }
153 --brace_close;
154
155 ks.body = std::string(stringified.substr(brace_open + 1, brace_close - brace_open - 1));
156 return ks;
157 }

References body, param_names, and raw.