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
16[[nodiscard]] consteval Error ParseFlags(std::string_view source, size_t& pos,
17 Conversion& conversion)
18{
19 while (pos < source.size())
20 {
21 switch (source[pos])
22 {
23 case '-':
24 conversion.left_align = true;
25 break;
26 case '+':
27 conversion.force_sign = true;
28 break;
29 case ' ':
30 conversion.space_sign = true;
31 break;
32 case '#':
33 if (!Config::enable_alternate)
34 {
35 return Error::InvalidSpecifier;
36 }
37 conversion.alternate = true;
38 break;
39 case '0':
40 conversion.zero_pad = true;
41 break;
42 default:
43 return Error::None;
44 }
45 ++pos;
46 }
47
48 return Error::None;
49}
50
58[[nodiscard]] consteval Error ParseWidth(std::string_view source, size_t& pos,
59 Conversion& conversion)
60{
61 if (pos < source.size() && source[pos] == '*')
62 {
63 return Error::DynamicField;
64 }
65
66 if (!Config::enable_width && pos < source.size() && IsDigit(source[pos]))
67 {
68 return Error::InvalidSpecifier;
69 }
70
71 return ParseByte(source, pos, std::numeric_limits<uint8_t>::max(),
72 conversion.width);
73}
74
82[[nodiscard]] consteval Error ParsePrecision(std::string_view source, size_t& pos,
83 Conversion& conversion)
84{
85 if (pos >= source.size() || source[pos] != '.')
86 {
87 return Error::None;
88 }
89
90 if (!Config::enable_precision)
91 {
92 return Error::InvalidSpecifier;
93 }
94
95 ++pos;
96 if (pos < source.size() && source[pos] == '*')
97 {
98 return Error::DynamicField;
99 }
100
101 if (pos < source.size() && IsDigit(source[pos]))
102 {
103 conversion.has_precision = true;
104 return ParseByte(
105 source, pos, static_cast<uint8_t>(std::numeric_limits<uint8_t>::max() - 1),
106 conversion.precision);
107 }
108
109 conversion.has_precision = true;
110 conversion.precision = 0;
111 return Error::None;
112}
113
120consteval void ParseLength(std::string_view source, size_t& pos,
121 Conversion& conversion)
122{
123 if (pos >= source.size())
124 {
125 return;
126 }
127
128 char token = source[pos];
129 if (token == 'h' || token == 'l')
130 {
131 ++pos;
132 conversion.length = (token == 'h') ? Length::Short : Length::Long;
133 if (pos < source.size() && source[pos] == token)
134 {
135 conversion.length = (token == 'h') ? Length::Char : Length::LongLong;
136 ++pos;
137 }
138 return;
139 }
140
141 switch (token)
142 {
143 case 'j':
144 conversion.length = Length::IntMax;
145 ++pos;
146 return;
147 case 'z':
148 conversion.length = Length::Size;
149 ++pos;
150 return;
151 case 't':
152 conversion.length = Length::PtrDiff;
153 ++pos;
154 return;
155 case 'L':
156 conversion.length = Length::LongDouble;
157 ++pos;
158 return;
159 default:
160 return;
161 }
162}
163
171[[nodiscard]] consteval Error ParseSpecifier(std::string_view source, size_t& pos,
172 Conversion& conversion)
173{
174 if (pos >= source.size())
175 {
176 return Error::UnexpectedEnd;
177 }
178
179 auto descriptor = FieldSelection::LookupSpecifier(source[pos]);
180 if (descriptor.type == ValueKind::None)
181 {
182 return Error::InvalidSpecifier;
183 }
184 if (!FieldSelection::LengthAllowed(descriptor.length_policy, conversion.length))
185 {
186 return Error::InvalidLength;
187 }
188 if (!FieldSelection::TypeEnabled(descriptor.gate, conversion.length))
189 {
190 return Error::InvalidSpecifier;
191 }
192
193 conversion.type = descriptor.type;
194 conversion.upper_case = conversion.upper_case || descriptor.upper_case;
195 ++pos;
196 return Error::None;
197}
198
207[[nodiscard]] consteval Error Parse(std::string_view source, size_t& pos,
208 IndexingState& indexing,
209 Conversion& conversion)
210{
211 ++pos;
212 if (pos >= source.size())
213 {
214 return Error::UnexpectedEnd;
215 }
216
217 auto error = ParseArgumentIndex(source, pos, indexing, conversion);
218 if (error != Error::None)
219 {
220 return error;
221 }
222
223 error = ParseFlags(source, pos, conversion);
224 if (error != Error::None)
225 {
226 return error;
227 }
228
229 error = ParseWidth(source, pos, conversion);
230 if (error != Error::None)
231 {
232 return error;
233 }
234
235 error = ParsePrecision(source, pos, conversion);
236 if (error != Error::None)
237 {
238 return error;
239 }
240
241 ParseLength(source, pos, conversion);
242 error = ParseSpecifier(source, pos, conversion);
243 if (error != Error::None)
244 {
245 return error;
246 }
247
248 error = FieldSelection::ValidateConversion(conversion);
249 if (error != Error::None)
250 {
251 return error;
252 }
253
254 if (!conversion.positional)
255 {
256 if (indexing.uses_positional)
257 {
258 return Error::MixedIndexing;
259 }
260
261 indexing.uses_sequential = true;
262 conversion.arg_index = indexing.next_index++;
263 }
264
265 return Error::None;
266}
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_sequential
at least one conversion used implicit sequential order / 至少有一个转换使用了隐式顺序参数
bool uses_positional
at least one conversion used n$ syntax / 至少有一个转换使用了 n$ 语法
size_t next_index
next sequential argument index / 下一个顺序参数索引