YSTest: Lexical.cpp 源文件

YSTest PreAlpha_b500_20140530 The YSLib Test Project

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

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
Lexical.cpp
浏览该文件的文档.
1 /*
2 © 2012-2014 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_Lexical
30 #include <ystdex/string.hpp> // for ystdex::get_mid;
31
32 namespace NPL
33 {
34
35 LexicalAnalyzer::LexicalAnalyzer()
36 : esc(-1), ld(), cbuf(), qlist()
37 {}
38
39 void
40 LexicalAnalyzer::HandleEscape()
41 {
42 YAssert(esc <= MaxEscapeLength, "Escape sequence is too long.");
43 if(esc == 1)
44 {
45 switch(*escs)
46 {
47 case '\\':
48 cbuf += '\\';
49 break;
50 case 'a':
51 cbuf += '\a';
52 break;
53 case 'b':
54 if(!cbuf.empty())
55 cbuf.pop_back();
56 break;
57 case 'f':
58 cbuf += '\f';
59 break;
60 case 'n':
61 cbuf += '\n';
62 break;
63 case 'r':
64 cbuf += '\r';
65 break;
66 case 't':
67 cbuf += '\t';
68 break;
69 case 'v':
70 cbuf += '\v';
71 break;
72 case '\'':
73 case '"':
74 if(*escs == ld)
75 {
76 cbuf += ld;
77 break;
78 }
79 default:
80 PushEscape();
81 return;
82 }
83 esc = -1;
84 }
85 else
86 PushEscape();
87 }
88
89 void
90 LexicalAnalyzer::PushEscape()
91 {
92 // cbuf += '^'; // test: 未转义。
93 yunseq(cbuf += '\\', escs[esc] = char());
94 yunseq(cbuf += escs, esc = -1);
95 }
96
97 void
98 LexicalAnalyzer::ParseByte(byte b)
99 {
100 if(!(b < 0x80))
101 {
102 //停止转义（转义序列不接受多字节字符）。
103 if(esc != size_t(-1))
104 PushEscape();
105 cbuf += char(b);
106 }
107 else if(esc != size_t(-1))
108 {
109 escs[esc++] = b;
110 HandleEscape();
111 }
112 else if(b == '\\' && ld != char())
113 esc = 0;
114 else
115 {
116 switch(b)
117 {
118 case '\'':
119 case '"':
120 if(ld == char())
121 {
122 // cbuf += '{'; // test;
123 ld = b;
124 qlist.push_back(cbuf.size());
125 cbuf += char(b);
126 }
127 else if(ld == b)
128 {
129 // cbuf += '}'; // test;
130 ld = char();
131 cbuf += char(b);
132 qlist.push_back(cbuf.size());
133 }
134 else
135 cbuf += char(b);
136 break;
137 case ' ':
138 case '\f':
139 case '\n':
140 // case '\r':
141 case '\t':
142 case '\v':
143 if(ld == char())
144 {
145 cbuf += ' ';
146 break;
147 }
148 default:
149 cbuf += char(b);
150 }
151 }
152 }
153
154 list<string>
155 LexicalAnalyzer::Literalize() const
156 {
157 size_t i(0);
158 list<string> result;
159
160 std::for_each(qlist.cbegin(), qlist.cend(), [&](const size_t& s){
161 if(s != i)
162 {
163 result.push_back(cbuf.substr(i, s - i));
164 i = s;
165 }
166 });
167 result.push_back(cbuf.substr(i));
168 return result;
169 }
170
171
172 char
173 CheckLiteral(const string& str)
174 {
175 if(str.size() < 2)
176 return char();
177 if(str.front() == '\'' && str.back() == '\'')
178 return '\'';
179 if(str.front() == '"' && str.back() == '"')
180 return '"';
181 return char();
182 }
183
184 string
185 Deliteralize(const string& str)
186 {
187 return CheckLiteral(str) == char() ? str : ystdex::get_mid(str);
188 }
189
190 string
191 MakeEscape(const string& str)
192 {
193 string res;
194
195 for(char c : str)
196 switch(c)
197 {
198 case '\a':
199 res += "\\a";
200 break;
201 case '\b':
202 res += "\\b";
203 break;
204 case '\f':
205 res += "\\f";
206 break;
207 case '\n':
208 res += "\\n";
209 break;
210 case '\r':
211 res += "\\r";
212 break;
213 case '\t':
214 res += "\\t";
215 break;
216 case '\v':
217 res += "\\v";
218 break;
219 default:
220 res += c;
221 }
222 if(!str.empty() && str.back() == '\\')
223 res += "\\";
224 return res;
225 }
226
227
228 list<string>
229 Decompose(const string& src_str)
230 {
231 list<string> dst;
232
233 ystdex::split_l(src_str.cbegin(), src_str.cend(), IsDelimeter, [&](
234 string::const_iterator b, string::const_iterator e){
235 string str(b, e);
236
237 YAssert(!str.empty(), "Null token found.");
238 if(IsGraphicalDelimeter(*b))
239 {
240 dst.push_back(str.substr(0, 1));
241 str.erase(0, 1);
242 }
243 // TODO: Optimize using %string_ref.
244 ystdex::trim(str);
245 if(!str.empty())
246 dst.push_back(std::move(str));
247 });
248 return dst;
249 }
250
251 list<string>
252 Tokenize(const list<string>& src)
253 {
254 list<string> dst;
255
256 for(const auto& str : src)
257 if(!str.empty())
258 {
259 if(str[0] != '\'' && str[0] != '"')
260 dst.splice(dst.end(), Decompose(str));
261 else
262 dst.push_back(str);
263 }
264 return dst;
265 }
266
267 } // namespace NPL;
268
NPL::MakeEscape
YF_API string MakeEscape(const string &)
转义字符串：替换指定字符串中的可转义字符。
Definition: Lexical.cpp:191
string.hpp
ISO C++ 标准字符串扩展。
NPL::LexicalAnalyzer::Literalize
list< string > Literalize() const
根据中间结果取字符串列表。
Definition: Lexical.cpp:155
NPL::Tokenize
YF_API list< string > Tokenize(const list< string > &)
记号化：提取字符串列表中的记号。
Definition: Lexical.cpp:252
NPL::Deliteralize
YF_API string Deliteralize(const string &)
去除字面量边界分隔符。
Definition: Lexical.cpp:185
ystdex::get_mid
_tString get_mid(const _tString &str, typename _tString::size_type l=1)
取删除前缀和后缀的子字符串。
Definition: string.hpp:256
NPL::LexicalAnalyzer::MaxEscapeLength
static yconstexpr size_t MaxEscapeLength
最大转义序列长度。
Definition: Lexical.h:77
ystdex::trim
_tString && trim(_tString &&str, typename string_traits< _tString >::const_pointer t=&to_array< typename string_traits< _tString >::value_type >("\n\r\t\v ")[0])
删除字符串中指定的连续前缀与后缀字符。
Definition: string.hpp:240
NPL::LexicalAnalyzer::ld
char ld
字面分隔符状态：表示正在处理字面量中的有效字符。
Definition: Lexical.h:95
ystdex::byte
unsigned char byte
字节类型。
Definition: ydef.h:555
NPL::IsGraphicalDelimeter
yconstfn bool IsGraphicalDelimeter(char c)
判断是否为 NPL 图形分隔符。
Definition: Lexical.h:165
NPL::LexicalAnalyzer::qlist
list< size_t > qlist
字符解析中间结果中非转义的引号出现的位置的有序列表。
Definition: Lexical.h:103
NPL::LexicalAnalyzer::cbuf
string cbuf
字符解析中间结果。
Definition: Lexical.h:99
NPL::Decompose
YF_API list< string > Decompose(const string &)
分解字符串为记号。
Definition: Lexical.cpp:229
YModules.h
NPL::LexicalAnalyzer::HandleEscape
void HandleEscape()
Definition: Lexical.cpp:40
NPL::LexicalAnalyzer::esc
size_t esc
转义状态：表示是否正在处理的有效转义序列的长度。
Definition: Lexical.h:85
NPL::CheckLiteral
YF_API char CheckLiteral(const string &)
检查指定字符串是否为字面量。
Definition: Lexical.cpp:173
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:748
NPL::LexicalAnalyzer::LexicalAnalyzer
LexicalAnalyzer()
Definition: Lexical.cpp:35
NPL::LexicalAnalyzer::PushEscape
void PushEscape()
Definition: Lexical.cpp:90
ystdex::split_l
_tIn split_l(_tIn b, _tIn e, _fPred is_delim, _fInsert insert)
以指定字符分割字符序列。
Definition: string.hpp:314
platform_ex::Windows::s
return s
Definition: MinGW32.cpp:49
NPL::IsDelimeter
yconstfn bool IsDelimeter(char c)
判断是否为 NPL 分隔符。
Definition: Lexical.h:177
NPL::LexicalAnalyzer::escs
char escs[MaxEscapeLength]
有效转义序列。
Definition: Lexical.h:90
CHRLib::c
c
Definition: chrproc.h:76
NPL::LexicalAnalyzer::ParseByte
void ParseByte(byte)
Definition: Lexical.cpp:98
YAssert
#define YAssert(_expr, _msg)
Definition: cassert.h:73