YSTest: NPLA.cpp 源文件

YSTest PreAlpha_b700_20160611 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

NPLA.cpp
浏览该文件的文档.
1 /*
2 © 2014-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "NPL/YModules.h"
29 #include YFM_NPL_NPLA
30 #include YFM_NPL_SContext
31
32 using namespace YSLib;
33
34 namespace NPL
35 {
36
37 ValueNode
38 MapNPLALeafNode(const TermNode& term)
39 {
40 return AsNode(string(),
41 string(Deliteralize(ParseNPLANodeString(MapToValueNode(term)))));
42 }
43
44 ValueNode
45 TransformToSyntaxNode(const ValueNode& node, const string& name)
46 {
47 ValueNode::Container con{AsIndexNode(size_t(), node.GetName())};
48 const auto nested_call([&](const ValueNode& nd){
49 con.emplace(TransformToSyntaxNode(nd, MakeIndex(con)));
50 });
51
52 if(node.empty())
53 {
54 if(const auto p = AccessPtr<NodeSequence>(node))
55 for(auto& nd : *p)
56 nested_call(nd);
57 else
58 con.emplace(NoContainer, MakeIndex(1),
59 Literalize(ParseNPLANodeString(node)));
60 }
61 else
62 for(auto& nd : node)
63 nested_call(nd);
64 return {std::move(con), name};
65 }
66
67 string
68 EscapeNodeLiteral(const ValueNode& node)
69 {
70 return EscapeLiteral(Access<string>(node));
71 }
72
73 string
74 LiteralizeEscapeNodeLiteral(const ValueNode& node)
75 {
76 return Literalize(EscapeNodeLiteral(node));
77 }
78
79 string
80 ParseNPLANodeString(const ValueNode& node)
81 {
82 return ystdex::value_or<string>(AccessPtr<string>(node));
83 }
84
85
86 string
87 DefaultGenerateIndent(size_t n)
88 {
89 return string(n, '\t');
90 }
91
92 void
93 PrintIndent(std::ostream& os, IndentGenerator igen, size_t n)
94 {
95 if(YB_LIKELY(n != 0))
96 ystdex::write(os, igen(n));
97 }
98
99 void
100 PrintNode(std::ostream& os, const ValueNode& node, NodeToString node_to_str,
101 IndentGenerator igen, size_t depth)
102 {
103 PrintIndent(os, igen, depth);
104 os << EscapeLiteral(node.GetName()) << ' ';
105 if(PrintNodeString(os, node, node_to_str))
106 return;
107 os << '\n';
108 if(node)
109 {
110 const auto nested_call(std::bind(PrintNodeChild, std::ref(os),
111 std::placeholders::_1, node_to_str, igen, depth));
112
113 // TODO: Null coalescing or variant value?
114 if(const auto p = AccessPtr<NodeSequence>(node))
115 for(const auto& nd : *p)
116 nested_call(nd);
117 else
118 for(const auto& nd : node)
119 nested_call(nd);
120 }
121 }
122
123 void
124 PrintNodeChild(std::ostream& os, const ValueNode& node,
125 NodeToString node_to_str, IndentGenerator igen, size_t depth)
126 {
127 PrintIndent(os, igen, depth);
128 if(IsPrefixedIndex(node.GetName()))
129 PrintNodeString(os, node, node_to_str);
130 else
131 {
132 os << '(' << '\n';
133 TryExpr(PrintNode(os, node, node_to_str, igen, depth + 1))
134 CatchIgnore(std::out_of_range&)
135 PrintIndent(os, igen, depth);
136 os << ')' << '\n';
137 }
138 }
139
140 bool
141 PrintNodeString(std::ostream& os, const ValueNode& node,
142 NodeToString node_to_str)
143 {
144 TryRet(os << node_to_str(node) << '\n', true)
145 CatchIgnore(ystdex::bad_any_cast&)
146 return {};
147 }
148
149
150 namespace SXML
151 {
152
153 string
154 ConvertAttributeNodeString(const TermNode& term)
155 {
156 switch(term.size())
157 {
158 default:
159 YTraceDe(Warning, "Invalid term with more than 2 children found.");
160 case 2:
161 {
162 auto i(term.begin());
163 const auto& n(Access<string>(Deref(i)));
164
165 return n + '=' + Access<string>(Deref(++i));
166 }
167 case 1:
168 return Access<string>(Deref(term.begin()));
169 case 0:
170 break;
171 }
172 throw LoggedEvent("Invalid term with less than 1 children found.", Warning);
173 }
174
175 string
176 ConvertDocumentNode(const TermNode& term, IndentGenerator igen, size_t depth,
177 ParseOption opt)
178 {
179 if(term)
180 {
181 string res(ConvertStringNode(term));
182
183 if(res.empty())
184 {
185 if(opt == ParseOption::String)
186 throw LoggedEvent("Invalid non-string term found.");
187
188 const auto& cont(term.GetContainer());
189
190 if(!cont.empty())
191 try
192 {
193 auto i(cont.cbegin());
194 const auto& str(Access<string>(Deref(i)));
195
196 ++i;
197 if(str == "@")
198 {
199 for(; i != cont.cend(); ++i)
200 res += ' ' + ConvertAttributeNodeString(Deref(i));
201 return res;
202 }
203 if(opt == ParseOption::Attribute)
204 throw LoggedEvent("Invalid non-attribute term found.");
205 if(str == "*PI*")
206 {
207 res = "<?";
208 for(; i != cont.cend(); ++i)
209 res += string(Deliteralize(ConvertDocumentNode(
210 Deref(i), igen, depth, ParseOption::String)))
211 + ' ';
212 if(!res.empty())
213 res.pop_back();
214 return res + "?>";
215 }
216 if(str == "*ENTITY*" || str == "*NAMESPACES*")
217 {
218 if(opt == ParseOption::Strict)
219 throw ystdex::unimplemented();
220 }
221 else if(str == "*COMMENT*")
222 ;
223 else if(!str.empty())
224 {
225 const bool is_content(str != "*TOP*");
226 string head('<' + str);
227 bool nl{};
228
229 if(YB_UNLIKELY(!is_content && depth > 0))
230 YTraceDe(Warning, "Invalid *TOP* found.");
231 if(i != cont.end())
232 {
233 if(!Deref(i).empty()
234 && (i->begin())->Value == string("@"))
235 {
236 head += string(
237 Deliteralize(ConvertDocumentNode(*i, igen,
238 depth, ParseOption::Attribute)));
239 if(++i == cont.cend())
240 return head + " />";
241 }
242 head += '>';
243 }
244 else
245 return head + " />";
246 for(; i != cont.cend(); ++i)
247 {
248 nl = Deref(i).Value.GetType()
249 != ystdex::type_id<string>();
250 if(nl)
251 res += '\n' + igen(depth + size_t(is_content));
252 else
253 res += ' ';
254 res += string(Deliteralize(ConvertDocumentNode(*i,
255 igen, depth + size_t(is_content))));
256 }
257 if(res.size() > 1 && res.front() == ' ')
258 res.erase(0, 1);
259 if(!res.empty() && res.back() == ' ')
260 res.pop_back();
261 if(is_content)
262 {
263 if(nl)
264 res += '\n' + igen(depth);
265 return head + res + ystdex::quote(str, "</", '>');
266 }
267 }
268 else
269 throw LoggedEvent("Empty item found.", Warning);
270 }
271 CatchExpr(ystdex::bad_any_cast& e, YTraceDe(Warning,
272 "Conversion failed: <%s> to <%s>.", e.from(), e.to()))
273 }
274 return res;
275 }
276 throw LoggedEvent("Empty term found.", Warning);
277 }
278
279 string
280 ConvertStringNode(const TermNode& term)
281 {
282 return ystdex::call_value_or<string>(EscapeXML, AccessPtr<string>(term));
283 }
284
285 void
286 PrintSyntaxNode(std::ostream& os, const TermNode& term, IndentGenerator igen,
287 size_t depth)
288 {
289 if(!term.empty())
290 ystdex::write(os,
291 ConvertDocumentNode(Deref(term.begin()), igen, depth), 1);
292 os << std::flush;
293 }
294
295
296 ValueNode
297 MakeXMLDecl(const string& name, const string& ver, const string& enc,
298 const string& sd)
299 {
300 auto decl("version=\"" + ver + '"');
301
302 if(!enc.empty())
303 decl += " encoding=\"" + enc + '"';
304 if(!sd.empty())
305 decl += " standalone=\"" + sd + '"';
306 return AsNodeLiteral(name, {{MakeIndex(0), "*PI*"}, {MakeIndex(1), "xml"},
307 {MakeIndex(2), decl + ' '}});
308 }
309
310 ValueNode
311 MakeXMLDoc(const string& name, const string& ver, const string& enc,
312 const string& sd)
313 {
314 auto doc(MakeTop(name));
315
316 doc.Add(MakeXMLDecl(MakeIndex(1), ver, enc, sd));
317 return doc;
318 }
319
320 } // namespace SXML;
321
322
323 ImplDeDtor(NPLException)
324
325
326 ImplDeDtor(ListReductionFailure)
327
328
329 ImplDeDtor(InvalidSyntax)
330
331
332 ImplDeDtor(UndeclaredIdentifier)
333
334
335 ArityMismatch::ArityMismatch(size_t e, size_t r)
336 : NPLException(ystdex::sfmt("Arity mismatch: expected %zu, received %zu.",
337 e, r)),
338 expected(e), received(r)
339 {}
340 ImplDeDtor(ArityMismatch)
341
342 void
343 ThrowArityMismatch(size_t expected, size_t received)
344 {
345 throw ArityMismatch(expected, received);
346 }
347
348
349 ValueObject
350 FetchValue(const ContextNode& ctx, const string& name)
351 {
352 return ystdex::call_value_or<ValueObject>(
353 std::mem_fn(&ValueNode::Value), LookupName(ctx, name));
354 }
355
356 observer_ptr<const ValueNode>
357 LookupName(const ContextNode& ctx, const string& id) ynothrow
358 {
359 return AccessNodePtr(ctx, id);
360 }
361
362
363 bool
364 DetectReducible(TermNode& term, bool reducible)
365 {
366 // TODO: Use explicit continuation parameters?
367 // if(reducible)
368 // k(term);
369 YSLib::RemoveEmptyChildren(term.GetContainerRef());
370 // NOTE: Only stopping on getting a normal form.
371 return reducible && !term.empty();
372 }
373
374 } // namespace NPL;
375
YSLib::RemoveEmptyChildren
YF_API void RemoveEmptyChildren(ValueNode::Container &) ynothrow
移除空子节点。
Definition: ValueNode.cpp:132
NPL::term
const TermNode &term ValueNode &node const ValueNode &node const TermNode & term
Definition: SContext.h:72
NPL::PrintIndent
YF_API void PrintIndent(std::ostream &, IndentGenerator=DefaultGenerateIndent, size_t=1)
打印缩进。
Definition: NPLA.cpp:93
CHRLib::enc
enc
Definition: CharacterProcessing.h:81
platform::p
while p p
Definition: YCLib/FileSystem.h:225
NPL::received
size_t received
Definition: NPLA.cpp:344
NPL::DetectReducible
YF_API bool DetectReducible(TermNode &, bool)
移除节点的空子节点，然后判断是否可继续规约。
Definition: NPLA.cpp:364
ystdex::sfmt
auto sfmt(const _tChar *fmt,...) -> decltype(vsfmt(fmt, std::declval< std::va_list >()))
以 C 标准输出格式的输出 std::basic_string 实例的对象。
Definition: string.hpp:1140
NPL::ArityMismatch
元数不匹配错误。
Definition: NPLA.h:445
platform::containers::string
basic_string< char > string
Definition: Container.h:101
platform::Descriptions::Warning
Definition: YCommon.h:157
YSLib::MakeIndex
MakeIndex
Definition: ValueNode.h:865
YSLib::ValueNode::begin
begin
Definition: ValueNode.h:398
NPL::A1::name
ctx const string & name
Definition: NPLA1.h:248
NPL::MapToValueNode
const TermNode &term MapToValueNode
Definition: SContext.h:61
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
ystdex::write
std::basic_ostream< _tChar, typename _tString::traits_type > & write(std::basic_ostream< _tChar, typename _tString::traits_type > &os, const _tString &str, typename _tString::size_type pos=0, typename _tString::size_type n=_tString::npos)
非格式输出。
Definition: string.hpp:921
NPL::SXML::ParseOption
ParseOption
限定解析选项。
Definition: NPL.h:60
NPL::InvalidSyntax
语法错误。
Definition: NPLA.h:421
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
YSLib::LoggedEvent
记录日志的异常事件类。
Definition: YException.h:49
NPL::MapNPLALeafNode
YF_API ValueNode MapNPLALeafNode(const TermNode &)
映射 NPLA 叶节点。
Definition: NPLA.cpp:38
platform::FAT::Attribute
Attribute
文件属性。
Definition: YCLib/FileSystem.h:742
NPL::SXML::PrintSyntaxNode
YF_API void PrintSyntaxNode(std::ostream &os, const TermNode &, IndentGenerator=DefaultGenerateIndent, size_t=0)
打印 SContext::Analyze 分析取得的 SXML 语法树节点并刷新流。
Definition: NPLA.cpp:286
NPL::EscapeXML
YF_API string EscapeXML(string_view)
编码 XML 字符串。
Definition: Lexical.cpp:339
NPL::SXML::ConvertStringNode
YF_API string ConvertStringNode(const TermNode &)
转换 SXML 节点为被转义的 XML 字符串。
Definition: NPLA.cpp:280
ystdex::mapped_set
允许指定不同于值类型的键的集合。
Definition: set.hpp:160
ystdex::bad_any_cast::to
const char * to() const
Definition: any.cpp:64
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:305
CatchIgnore
#define CatchIgnore(_ex)
指定异常处理器忽略指定异常。
Definition: YBaseMacro.h:133
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
ystdex::bad_any_cast
动态泛型转换失败异常。
Definition: any.h:636
NPL::PrintNode
YF_API void PrintNode(std::ostream &, const ValueNode &, NodeToString=EscapeNodeLiteral, IndentGenerator=DefaultGenerateIndent, size_t=0)
打印 NPLA 节点。
Definition: NPLA.cpp:100
YSLib::AccessNodePtr
name AccessNodePtr
Definition: ValueNode.h:627
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:438
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:440
TryExpr
#define TryExpr(...)
指定表达式在 try 块中求值。
Definition: YBaseMacro.h:120
YModules.h
NPL::LiteralizeEscapeNodeLiteral
YF_API string LiteralizeEscapeNodeLiteral(const ValueNode &)
转义 NPLA 节点字面量。
Definition: NPLA.cpp:74
NPL::Deliteralize
YF_API string_view Deliteralize(string_view) ynothrowv
去除字面量边界分隔符。
Definition: Lexical.cpp:247
YSLib::IsPrefixedIndex
bool IsPrefixedIndex(string_view name, char prefix)
Definition: ValueNode.cpp:148
ystdex
特性测试宏。
Definition: ydef.h:796
YSLib::Text::str
const char const char * str
Definition: TextFile.h:77
NPL::SXML::MakeTop
ValueNode MakeTop(const string &name, _tParams &&...args)
构造 SXML 文档顶级节点。
Definition: NPLA.h:302
NPL
Definition: NPL/Configuration.h:34
YSLib::ValueNode::empty
const container container empty
Definition: ValueNode.h:410
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
NPL::ParseNPLANodeString
YF_API string ParseNPLANodeString(const ValueNode &)
解析 NPLA 节点字符串。
Definition: NPLA.cpp:80
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
NPL::SXML::ConvertDocumentNode
YF_API string ConvertDocumentNode(const TermNode &, IndentGenerator=DefaultGenerateIndent, size_t=0, ParseOption=ParseOption::Normal)
转换 SXML 文档节点为 XML 字符串。
Definition: NPLA.cpp:176
NPL::Literalize
YF_API string Literalize(string_view, char= '"')
修饰字符串为字面量。
Definition: Lexical.cpp:369
NPL::TransformToSyntaxNode
YF_API ValueNode TransformToSyntaxNode(const ValueNode &, const string &={})
变换节点为语法分析树叶节点。
Definition: NPLA.cpp:45
YSLib::ValueNode::Value
ValueObject Value
Definition: ValueNode.h:83
YSLib::i
return i
Definition: YCoreUtilities.h:176
NPL::SXML::ConvertAttributeNodeString
YF_API string ConvertAttributeNodeString(const TermNode &)
转换 SXML 节点为 XML 属性字符串。
Definition: NPLA.cpp:154
NPL::NodeToString
std::function< string(const ValueNode &)> NodeToString
Definition: NPLA.h:96
NPL::LookupName
YF_API observer_ptr< const ValueNode > LookupName(const ContextNode &, const string &) ynothrow
从指定上下文查找名称对应的节点。
Definition: NPLA.cpp:357
NPL::PrintNodeString
YF_API bool PrintNodeString(std::ostream &, const ValueNode &, NodeToString=EscapeNodeLiteral)
打印节点字符串。
Definition: NPLA.cpp:141
YB_LIKELY
#define YB_LIKELY(_expr)
Definition: ydef.h:437
NPL::EscapeLiteral
YF_API string EscapeLiteral(string_view)
编码转义字符串字面量。
Definition: Lexical.cpp:327
YSLib::ImplDeDtor
ImplDeDtor(LoggedEvent) FatalError
Definition: YException.cpp:47
YSLib::ValueNode
值类型节点。
Definition: ValueNode.h:57
YSLib::ValueNode::size
const const ValueNode &node size
Definition: ValueNode.h:464
NPL::FetchValue
ValueObject FetchValue(const ContextNode &ctx, const string &name)
Definition: NPLA.cpp:350
NPL::SXML::MakeXMLDecl
YF_API ValueNode MakeXMLDecl(const string &={}, const string &="1.0", const string &="UTF-8", const string &={})
构造 SXML 文档 XML 声明节点。
Definition: NPLA.cpp:297
NPL::ListReductionFailure
列表规约失败。
Definition: NPLA.h:408
NPL::EscapeNodeLiteral
YF_API string EscapeNodeLiteral(const ValueNode &)
转义 NPLA 节点字面量。
Definition: NPLA.cpp:68
NPL::NPLException
NPL 异常基类。
Definition: NPLA.h:385
NPL::PrintNodeChild
YF_API void PrintNodeChild(std::ostream &, const ValueNode &, NodeToString=EscapeNodeLiteral, IndentGenerator=DefaultGenerateIndent, size_t=0)
打印作为子节点的 NPLA 节点。
Definition: NPLA.cpp:124
NPL::SXML::MakeXMLDoc
YF_API ValueNode MakeXMLDoc(const string &={}, const string &="1.0", const string &="UTF-8", const string &={})
构造包含 XML 声明的 SXML 文档节点。
Definition: NPLA.cpp:311
ystdex::unimplemented
异常：未实现的操作。
Definition: ystdex/exception.h:135
ystdex::quote
_tString quote(const _tString &str, typename string_traits< _tString >::value_type c=typename string_traits< _tString >::value_type('"'))
取添加前缀和后缀的字符串。
Definition: string.hpp:741
YSLib::ValueObject
值类型对象类。
Definition: YObject.h:272
NPL::IndentGenerator
std::function< string(size_t)> IndentGenerator
生成前缀缩进的函数类型。
Definition: NPLA.h:189
YSLib::AsIndexNode
const ValueNode &node typename _tParams ValueNode AsIndexNode(_tParam &&arg, _tParams &&...args)
Definition: ValueNode.h:876
NPL::DefaultGenerateIndent
YF_API string DefaultGenerateIndent(size_t)
生成水平制表符为单位的缩进。
Definition: NPLA.cpp:87
ystdex::bad_any_cast::from
const char * from() const
Definition: any.cpp:57
platform::n
size_t n
Definition: YCLib/FileSystem.cpp:321
YSLib::NoContainer
yconstexpr const struct YSLib::NoContainerTag NoContainer
ystdex::ref
lref< _type > ref(_type &t)
构造引用包装。
Definition: ref.hpp:120
NPL::UndeclaredIdentifier
未声明标识符错误。
Definition: NPLA.h:433