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 
36  : esc(-1), ld(), cbuf(), qlist()
37 {}
38 
39 void
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
91 {
92 // cbuf += '^'; // test: 未转义。
93  yunseq(cbuf += '\\', escs[esc] = char());
94  yunseq(cbuf += escs, esc = -1);
95 }
96 
97 void
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>
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 
YF_API string MakeEscape(const string &)
转义字符串:替换指定字符串中的可转义字符。
Definition: Lexical.cpp:191
ISO C++ 标准字符串扩展。
list< string > Literalize() const
根据中间结果取字符串列表。
Definition: Lexical.cpp:155
YF_API list< string > Tokenize(const list< string > &)
记号化:提取字符串列表中的记号。
Definition: Lexical.cpp:252
YF_API string Deliteralize(const string &)
去除字面量边界分隔符。
Definition: Lexical.cpp:185
_tString get_mid(const _tString &str, typename _tString::size_type l=1)
取删除前缀和后缀的子字符串。
Definition: string.hpp:256
static yconstexpr size_t MaxEscapeLength
最大转义序列长度。
Definition: Lexical.h:77
_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
char ld
字面分隔符状态:表示正在处理字面量中的有效字符。
Definition: Lexical.h:95
unsigned char byte
字节类型。
Definition: ydef.h:555
yconstfn bool IsGraphicalDelimeter(char c)
判断是否为 NPL 图形分隔符。
Definition: Lexical.h:165
list< size_t > qlist
字符解析中间结果中非转义的引号出现的位置的有序列表。
Definition: Lexical.h:103
string cbuf
字符解析中间结果。
Definition: Lexical.h:99
YF_API list< string > Decompose(const string &)
分解字符串为记号。
Definition: Lexical.cpp:229
size_t esc
转义状态:表示是否正在处理的有效转义序列的长度。
Definition: Lexical.h:85
YF_API char CheckLiteral(const string &)
检查指定字符串是否为字面量。
Definition: Lexical.cpp:173
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:748
_tIn split_l(_tIn b, _tIn e, _fPred is_delim, _fInsert insert)
以指定字符分割字符序列。
Definition: string.hpp:314
yconstfn bool IsDelimeter(char c)
判断是否为 NPL 分隔符。
Definition: Lexical.h:177
char escs[MaxEscapeLength]
有效转义序列。
Definition: Lexical.h:90
void ParseByte(byte)
Definition: Lexical.cpp:98
#define YAssert(_expr, _msg)
Definition: cassert.h:73