2 #include "src/exception_macro.h"
3 #include "src/lexer/string_lexer.h"
4 #include "src/lexer/term_lexer.h"
5 #include "src/lexer/term_checker.h"
6 #include "src/lexeme.h"
7 #include "src/encoding_reader.h"
8 #include "src/unicode.h"
10 namespace lexer = utakata::lexer;
11 namespace term = utakata::lexer::term;
12 namespace reader = utakata::reader;
13 namespace unicode = utakata::unicode;
17 bool lexer::EscapeLexer::Lex(reader::EncodingReader* reader,
19 unicode::UniString escape(reader->Read(kEscapeValidLength));
20 if (escape.IsEmpty() || escape.At(0).rawcode != '\\') {
24 if (escape.GetSize() < kEscapeValidLength) {
25 THROW_EXCEPTION_(lexer::LexException,
26 unicode::Convert("invalid escape sequence"));
29 lexer::InlineHexEscapeLexer inline_escape;
31 if (inline_escape(reader, code)) {
36 lexer::TermLexer<term::IntralineWhiteSpaceChecker> intraline;
37 lexer::TermLexer<term::LineEndingChecker> lineend;
38 if (!CheckEscapeSequence(escape.At(1)) &&
39 !intraline.CheckToken(reader) &&
40 !lineend.CheckToken(reader)) {
41 unicode::UniString encoded_string("invalid escape sequence : ");
42 encoded_string.Append(escape);
43 THROW_EXCEPTION_(lexer::LexException, encoded_string);
46 *code = ConvertEscapeToCode(escape, reader);
50 // \<intraline whitespace>に該当する場合、返却されるcodeは0と
52 unsigned int lexer::EscapeLexer::ConvertEscapeToCode(
53 const unicode::UniString& escape, reader::EncodingReader* reader) {
54 unsigned int code = 0;
55 lexer::TermLexer<term::IntralineWhiteSpaceChecker> intraline;
56 lexer::TermLexer<term::LineEndingChecker> lineend;
58 if (!intraline.CheckToken(reader) && !lineend.CheckToken(reader)) {
59 lexer::EscapeConverter converter;
60 if (converter.CanConvert(escape.At(1).rawcode())) {
61 code = converter.Convert(escape.At(1).rawcode());
63 unicode::UniString encoded_string(
64 unicode::Convert("invalid escape sequence : "));
65 encoded_string.Append(escape);
66 THROW_EXCEPTION_(lexer::LexException, encoded_string);
69 // 1文字だけReadしているのは、すでに\に該当する部分がReadされており、
70 // escapeとして渡されている文字列以降をチェックするために、
73 while (intraline.CheckToken(reader) && !reader->IsEof()) {
74 intraline.ReadToken(reader);
77 if (!lineend.CheckToken(reader)) {
78 unicode::UniString encoded_string;
79 THROW_EXCEPTION_(lexer::LexException,
80 unicode::Convert("must line ending after whitespaces"));
82 lineend.ReadToken(reader);
84 while (intraline.CheckToken(reader) && !reader->IsEof()) {
85 intraline.ReadToken(reader);
93 bool lexer::EscapeConverter::CanConvert(unsigned int code) {
111 unsigned int lexer::EscapeConverter::Convert(unsigned int code) {
113 case 'a' : return kAlarm;
114 case 'b' : return kBackspace;
115 case 't' : return kTab;
116 case 'n' : return kLinefeed;
117 case 'v' : return kVTab;
118 case 'f' : return kForward;
119 case 'r' : return kCaridgeReturn;
120 case '"' : return kDoubleQuote;
121 case '\\' : return kBackslash;
126 // 文字列の終了地点は、同一行の`"`か、\\を含む複数行後の対応する`"`となります。
127 // 対応する`"`が存在しないままreaderの末尾に到達すると、LexExceptionが
129 // また、\から行末まで空白文字のみが続き、次の行の最初の文字までが、改行か
130 // 空白のみである場合、その間の空白及び改行は無視され、文字列は継続している
132 lexer::Lexeme* lexer::StringLexer::Lex(reader::EncodingReader* reader) {
133 term::StringDelimiterChecker string_delimiter;
135 unicode::UniChar head(reader->Read());
136 if (!string_delimiter(head)) {
141 term::StarndardDelimiterChecker std_delimiter;
142 term::WhitespaceChecker white_delimiter;
143 term::LineEndingChecker lineending_checker;
145 unicode::UniString str;
146 bool syntax_ok = false;
148 while (!reader->IsEof() && !syntax_ok) {
149 unicode::UniChar tmp(reader->Peek());
151 if (string_delimiter(tmp)) {
157 if (lineending_checker(tmp)) {
158 while (!reader->IsEof() && (white_delimiter(tmp) || std_delimiter(tmp))) {
162 str.Append(unicode::UniChar(reader->Read()));
167 THROW_EXCEPTION_(lexer::LexException,
168 unicode::Convert("not found end of string."));
171 return new lexer::Lexeme(str, lexer::Lexeme::kString);