libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
printf_frontend_parser.hpp
1#pragma once
2
3#include "printf_frontend_parse_util.hpp"
4
18[[nodiscard]] consteval Error ParseFlags(std::string_view source, size_t& pos,
19 Conversion& conversion)
20{
21 while (pos < source.size())
22 {
23 switch (source[pos])
24 {
25 case '-':
26 conversion.left_align = true;
27 break;
28 case '+':
29 conversion.force_sign = true;
30 break;
31 case ' ':
32 conversion.space_sign = true;
33 break;
34 case '#':
35 if (!Config::enable_alternate)
36 {
37 return Error::InvalidSpecifier;
38 }
39 conversion.alternate = true;
40 break;
41 case '0':
42 conversion.zero_pad = true;
43 break;
44 default:
45 return Error::None;
46 }
47 ++pos;
48 }
49
50 return Error::None;
51}
52
62[[nodiscard]] consteval Error ParseWidth(std::string_view source, size_t& pos,
63 Conversion& conversion)
64{
65 if (pos < source.size() && source[pos] == '*')
66 {
67 return Error::DynamicField;
68 }
69
70 if (!Config::enable_width && pos < source.size() && IsDigit(source[pos]))
71 {
72 return Error::InvalidSpecifier;
73 }
74
75 return ParseByte(source, pos, std::numeric_limits<uint8_t>::max(), conversion.width);
76}
77
87[[nodiscard]] consteval Error ParsePrecision(std::string_view source, size_t& pos,
88 Conversion& conversion)
89{
90 if (pos >= source.size() || source[pos] != '.')
91 {
92 return Error::None;
93 }
94
95 if (!Config::enable_precision)
96 {
97 return Error::InvalidSpecifier;
98 }
99
100 ++pos;
101 if (pos < source.size() && source[pos] == '*')
102 {
103 return Error::DynamicField;
104 }
105
106 if (pos < source.size() && IsDigit(source[pos]))
107 {
108 conversion.has_precision = true;
109 return ParseByte(source, pos,
110 static_cast<uint8_t>(std::numeric_limits<uint8_t>::max() - 1),
111 conversion.precision);
112 }
113
114 conversion.has_precision = true;
115 conversion.precision = 0;
116 return Error::None;
117}
118
126consteval void ParseLength(std::string_view source, size_t& pos, Conversion& conversion)
127{
128 if (pos >= source.size())
129 {
130 return;
131 }
132
133 char token = source[pos];
134 if (token == 'h' || token == 'l')
135 {
136 ++pos;
137 conversion.length = (token == 'h') ? Length::Short : Length::Long;
138 if (pos < source.size() && source[pos] == token)
139 {
140 conversion.length = (token == 'h') ? Length::Char : Length::LongLong;
141 ++pos;
142 }
143 return;
144 }
145
146 switch (token)
147 {
148 case 'j':
149 conversion.length = Length::IntMax;
150 ++pos;
151 return;
152 case 'z':
153 conversion.length = Length::Size;
154 ++pos;
155 return;
156 case 't':
157 conversion.length = Length::PtrDiff;
158 ++pos;
159 return;
160 case 'L':
161 conversion.length = Length::LongDouble;
162 ++pos;
163 return;
164 default:
165 return;
166 }
167}
168
179[[nodiscard]] consteval Error ParseSpecifier(std::string_view source, size_t& pos,
180 Conversion& conversion)
181{
182 if (pos >= source.size())
183 {
184 return Error::UnexpectedEnd;
185 }
186
187 auto descriptor = FieldSelection::LookupSpecifier(source[pos]);
188 if (descriptor.type == ValueKind::None)
189 {
190 return Error::InvalidSpecifier;
191 }
192 if (!FieldSelection::LengthAllowed(descriptor.length_policy, conversion.length))
193 {
194 return Error::InvalidLength;
195 }
196 if (!FieldSelection::TypeEnabled(descriptor.gate, conversion.length))
197 {
198 return Error::InvalidSpecifier;
199 }
200
201 conversion.type = descriptor.type;
202 conversion.upper_case = conversion.upper_case || descriptor.upper_case;
203 ++pos;
204 return Error::None;
205}
206
218[[nodiscard]] consteval Error Parse(std::string_view source, size_t& pos,
219 IndexingState& indexing, Conversion& conversion)
220{
221 ++pos;
222 if (pos >= source.size())
223 {
224 return Error::UnexpectedEnd;
225 }
226
227 auto error = ParseArgumentIndex(source, pos, indexing, conversion);
228 if (error != Error::None)
229 {
230 return error;
231 }
232
233 error = ParseFlags(source, pos, conversion);
234 if (error != Error::None)
235 {
236 return error;
237 }
238
239 error = ParseWidth(source, pos, conversion);
240 if (error != Error::None)
241 {
242 return error;
243 }
244
245 error = ParsePrecision(source, pos, conversion);
246 if (error != Error::None)
247 {
248 return error;
249 }
250
251 ParseLength(source, pos, conversion);
252 error = ParseSpecifier(source, pos, conversion);
253 if (error != Error::None)
254 {
255 return error;
256 }
257
258 error = FieldSelection::ValidateConversion(conversion);
259 if (error != Error::None)
260 {
261 return error;
262 }
263
264 if (!conversion.positional)
265 {
266 if (indexing.uses_positional)
267 {
268 return Error::MixedIndexing;
269 }
270
271 indexing.uses_sequential = true;
272 conversion.arg_index = indexing.next_index++;
273 }
274
275 return Error::None;
276}
Error
brace 风格 format 前端的编译期失败类别。 / Compile-time failure categories for the brace-style format frontend.
consteval Error ParseByte(std::string_view source, size_t &pos, uint8_t limit, uint8_t &value)
解析一个目标为字节宽度的十进制整数字段片段,并检查是否溢出 / Parse one decimal byte-sized integer fragment with overflow checking
consteval Error ParseArgumentIndex(std::string_view source, size_t &pos, IndexingState &indexing, Conversion &conversion)
解析可选的前导 n$ 位置参数选择器 / Parse the optional leading n$ positional argument selector
consteval Error ParseWidth(std::string_view source, size_t &pos, Conversion &conversion)
解析一个可选的常量宽度字段 / Parse one optional constant width field
consteval void ParseLength(std::string_view source, size_t &pos, Conversion &conversion)
解析一个可选的长度修饰符序列 / Parse one optional length modifier sequence
consteval Error ParsePrecision(std::string_view source, size_t &pos, Conversion &conversion)
解析一个可选的常量精度字段 / Parse one optional constant precision field
consteval Error ParseSpecifier(std::string_view source, size_t &pos, Conversion &conversion)
解析并校验最终的转换说明符字符 / Parse and validate the final conversion specifier token
consteval Error Parse(std::string_view source, size_t &pos, IndexingState &indexing, Conversion &conversion)
在前导 % 之后解析一个完整 printf 转换项 / Parse one complete printf conversion after the leading %
consteval Error ParseFlags(std::string_view source, size_t &pos, Conversion &conversion)
单个 printf 转换体的源级解析器 / Source parser for one printf conversion body
单个 printf 转换在降为共享格式前的解析结果 / One parsed printf conversion before lowering into the shared format
ValueKind type
semantic conversion category / 转换项归一化后的语义类别
bool upper_case
implied uppercase output / 隐含的大写输出标志
bool left_align
parsed - flag / 已解析的 - 标志
Length length
parsed length modifier / 已解析的长度修饰符
uint8_t width
parsed field width / 已解析的字段宽度
bool force_sign
parsed + flag / 已解析的 + 标志
bool positional
whether arg_index came from n$ syntax / arg_index 是否来自 n$ 语法
bool zero_pad
parsed 0 flag / 已解析的 0 标志
bool space_sign
parsed space-sign flag / 已解析的空格正号标志
size_t arg_index
source argument index consumed by this field / 当前字段消耗的源参数索引
bool alternate
parsed # flag / 已解析的 # 标志
uint8_t precision
parsed precision value / 已解析的精度值
bool has_precision
whether precision was explicitly provided / 是否显式提供了精度
brace 字段自动索引与手动索引的源级状态 / Source-level indexing mode for automatic versus manual brace fields
bool uses_positional
at least one conversion used n$ syntax / 至少有一个转换使用了 n$ 语法
size_t next_index
next sequential argument index / 下一个顺序参数索引