+#include <utility>
#include "src/exception_macro.h"
#include "src/lexer/string_lexer.h"
#include "src/lexer/term_lexer.h"
namespace reader = utakata::reader;
namespace unicode = utakata::unicode;
+
// 宣言のコメントを参照して下さい。
bool lexer::EscapeLexer::Lex(reader::EncodingReader* reader,
unsigned int* code) {
if (escape.GetSize() < kEscapeValidLength) {
THROW_EXCEPTION_(lexer::LexException,
- unicode::Convert("invalid escape seacense"));
+ unicode::Convert("invalid escape sequence"));
}
- term::IntralineWhiteSpaceChecker intraline;
- term::LineEndingChecker lineend;
- if (!CheckEscapeSeacense(escape.At(1)) && !intraline(escape.At(1)) &&
- !lineend(escape.At(1))) {
- unicode::UniString encoded_string("invalid escape seacense : ");
+ lexer::InlineHexEscapeLexer inline_escape;
+
+ if (inline_escape(reader, code)) {
+ return true;
+ }
+
+ reader->Read();
+ lexer::TermLexer<term::IntralineWhiteSpaceChecker> intraline;
+ lexer::TermLexer<term::LineEndingChecker> lineend;
+ if (!CheckEscapeSequence(escape.At(1)) &&
+ !intraline.CheckToken(reader) &&
+ !lineend.CheckToken(reader)) {
+ unicode::UniString encoded_string("invalid escape sequence : ");
encoded_string.Append(escape);
THROW_EXCEPTION_(lexer::LexException, encoded_string);
}
- if (!intraline(escape.At(1)) && !lineend(escape.At(1))) {
- *code = ConvertEscapeToCode(escape);
+ *code = ConvertEscapeToCode(escape, reader);
+ return true;
+}
+
+// \<intraline whitespace>に該当する場合、返却されるcodeは0と
+// なります。
+unsigned int lexer::EscapeLexer::ConvertEscapeToCode(
+ const unicode::UniString& escape, reader::EncodingReader* reader) {
+ unsigned int code = 0;
+ lexer::TermLexer<term::IntralineWhiteSpaceChecker> intraline;
+ lexer::TermLexer<term::LineEndingChecker> lineend;
+
+ if (!intraline.CheckToken(reader) && !lineend.CheckToken(reader)) {
+ lexer::EscapeConverter converter;
+ if (converter.CanConvert(escape.At(1).rawcode())) {
+ code = converter.Convert(escape.At(1).rawcode());
+ } else {
+ unicode::UniString encoded_string(
+ unicode::Convert("invalid escape sequence : "));
+ encoded_string.Append(escape);
+ THROW_EXCEPTION_(lexer::LexException, encoded_string);
+ }
} else {
- reader->Read(kEscapeValidLength);
- unicode::UniChar checker(escape.At(1));
- while (intraline(checker) && !reader->IsEof()) {
- checker = unicode::UniChar(reader->Read());
+ // 1文字だけReadしているのは、すでに\に該当する部分がReadされており、
+ // escapeとして渡されている文字列以降をチェックするために、
+ // escape分を読捨てるためです。
+ reader->Read();
+ while (intraline.CheckToken(reader) && !reader->IsEof()) {
+ intraline.ReadToken(reader);
}
- if (!lineend(checker)) {
+ if (!lineend.CheckToken(reader)) {
unicode::UniString encoded_string;
THROW_EXCEPTION_(lexer::LexException,
unicode::Convert("must line ending after whitespaces"));
}
+ lineend.ReadToken(reader);
- while (intraline(checker) && !reader->IsEof()) {
- reader->Read();
- checker = unicode::UniChar(reader->Peek());
+ while (intraline.CheckToken(reader) && !reader->IsEof()) {
+ intraline.ReadToken(reader);
}
- *code = 0;
}
- return true;
+ return code;
+}
+
+// 宣言のコメントを参照して下さい。
+bool lexer::EscapeConverter::CanConvert(unsigned int code) {
+ switch (code) {
+ case 'a' :
+ case 'b' :
+ case 't' :
+ case 'n' :
+ case 'v' :
+ case 'f' :
+ case 'r' :
+ case '"' :
+ case '\\' :
+ return true;
+ default:
+ return false;
+ }
+}
+
+// 宣言のコメントを参照してください。
+unsigned int lexer::EscapeConverter::Convert(unsigned int code) {
+ switch (code) {
+ case 'a' : return kAlarm;
+ case 'b' : return kBackspace;
+ case 't' : return kTab;
+ case 'n' : return kLinefeed;
+ case 'v' : return kVTab;
+ case 'f' : return kForward;
+ case 'r' : return kCaridgeReturn;
+ case '"' : return kDoubleQuote;
+ case '\\' : return kBackslash;
+ default: return 0;
+ }
}
// 文字列の終了地点は、同一行の`"`か、\\を含む複数行後の対応する`"`となります。
#ifndef _UTAKATA_SRC_LEXER_STRING_LEXER_H_
#define _UTAKATA_SRC_LEXER_STRING_LEXER_H_
+#include <map>
#include "src/lexer/lexer_interface.h"
namespace utakata {
namespace lexer {
class Lexeme;
+
+// エスケープ文字を判定し、各固定値を返却するためのfunctorです。
+class EscapeConverter {
+ // 各エスケープシーケンスに対する定数値です。
+ // この定数群には、inline hex escapeは利用されません。
+ static const unsigned int kAlarm = 0x07;
+ static const unsigned int kBackspace = 0x08;
+ static const unsigned int kTab = 0x09;
+ static const unsigned int kLinefeed = 0x0A;
+ static const unsigned int kVTab = 0x0B;
+ static const unsigned int kForward = 0x0C;
+ static const unsigned int kCaridgeReturn = 0x0D;
+ static const unsigned int kDoubleQuote = 0x22;
+ static const unsigned int kBackslash = 0x5C;
+
+public:
+
+ // エスケープシーケンスの文字コードである場合、trueを返します。
+ bool CanConvert(unsigned int code);
+
+ // エスケープシーケンスの文字コードから、各エスケープシーケンスに
+ // 該当する値を返却します。
+ // 該当するエスケープシーケンスが存在しない場合、0を返却します。
+ unsigned int Convert(unsigned int code);
+};
+
// エスケープ文字列を判定し、該当する文字コードを返却するLexerです。
// このクラスで判定されるエスケープシーケンスは以下になります。
// \a ベル 0x07
// エスケープシーケンスを判断する際に、判断基準とする読出
// 文字数です。
static const int kEscapeValidseLength = 2;
+
public:
EscapeLexer() {}
virtual ~EscapeLexer() {}
bool CheckEscapeSeacense(const unicode::UniChar& escape);
// 渡されたエスケープシーケンスから、該当する文字コードを取得します。
+ // 内部では、\<intraline whitespace>...のチェックも行います。
// エスケープシーケンスとして認識されない文字列が渡された場合、
// LexExceptionを送出します。
- unsigned int ConvertEscapeToCode(const unicode::UniString& escape);
+ unsigned int ConvertEscapeToCode(const unicode::UniString& escape,
+ reader::EncodingReader* reader);
};
class StringLexer : public IPartOfLexer {