OSDN Git Service

delimiter.h/cppを、term_lexer、term_checkerとしてテンプレートを利用するように分離した。
[simplecms/utakata.git] / src / lexer / string_lexer.cpp
index 48f4a8e..2ed7081 100755 (executable)
@@ -1,42 +1,81 @@
 #include "src/exception_macro.h"
 #include "src/lexer/string_lexer.h"
-#include "src/lexer/delimiters.h"
+#include "src/lexer/term_lexer.h"
+#include "src/lexer/term_checker.h"
 #include "src/lexeme.h"
 #include "src/encoding_reader.h"
 #include "src/unicode.h"
 
 namespace lexer = utakata::lexer;
-namespace delimiter = utakata::lexer_delimiter;
+namespace term = utakata::lexer::term;
 namespace reader = utakata::reader;
 namespace unicode = utakata::unicode;
 
-// 宣言のコメントを参照してください。
-bool lexer::StringDispatchTerm::IsDispatch(
-    const unicode::UniString& string) const {
-  if (!string.IsEmpty() && string.At(0).rawcode() == '"') {
-    return true;
+// 宣言のコメントを参照して下さい。
+bool lexer::EscapeLexer::Lex(reader::EncodingReader* reader,
+                             unsigned int* code) {
+  unicode::UniString escape(reader->Read(kEscapeValidLength));
+  if (escape.IsEmpty() || escape.At(0).rawcode != '\\') {
+    return false;
   }
 
-  return false;
+  if (escape.GetSize() < kEscapeValidLength) {
+    THROW_EXCEPTION_(lexer::LexException,
+                     unicode::Convert("invalid escape seacense"));
+  }
+
+  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 : ");
+    encoded_string.Append(escape);
+    THROW_EXCEPTION_(lexer::LexException, encoded_string);
+  }
+
+  if (!intraline(escape.At(1)) && !lineend(escape.At(1))) {
+    *code = ConvertEscapeToCode(escape);
+  } else {
+    reader->Read(kEscapeValidLength);
+    unicode::UniChar checker(escape.At(1));
+    while (intraline(checker) && !reader->IsEof()) {
+      checker = unicode::UniChar(reader->Read());
+    }
+
+    if (!lineend(checker)) {
+      unicode::UniString encoded_string;
+      THROW_EXCEPTION_(lexer::LexException,
+                       unicode::Convert("must line ending after whitespaces"));
+    }
+
+    while (intraline(checker) && !reader->IsEof()) {
+      reader->Read();
+      checker = unicode::UniChar(reader->Peek());
+    }
+    *code = 0;
+  }
+
+  return true;
 }
 
 // 文字列の終了地点は、同一行の`"`か、\\を含む複数行後の対応する`"`となります。
 // 対応する`"`が存在しないままreaderの末尾に到達すると、LexExceptionが
 // 送出されます。
-// また、行末から次の行の最初の文字までが、改行か空白のみである場合、
-// 行末から次の空白以外の文字までの文字列は無視され、文字列は継続している
+// また、\から行末まで空白文字のみが続き、次の行の最初の文字までが、改行か
+// 空白のみである場合、その間の空白及び改行は無視され、文字列は継続している
 // とみなされます。
-lexer::Lexeme* lexer::StringLexer::Lex(const unicode::UniString& string,
-                                       reader::EncodingReader* reader) {
-  if (reader == NULL) {
-    THROW_EXCEPTION_(lexer::LexException, unicode::Convert(
-        "reader must valid instance"));
+lexer::Lexeme* lexer::StringLexer::Lex(reader::EncodingReader* reader) {
+  term::StringDelimiterChecker string_delimiter;
+  {
+    unicode::UniChar head(reader->Read());
+    if (!string_delimiter(head)) {
+      return NULL;
+    }
   }
 
-  delimiter::StarndardDelimiterChecker std_delimiter;
-  delimiter::StringDelimiterChecker string_delimiter;
-  delimiter::WhitespaceChecker white_delimiter;
-  delimiter::LineEndingChecker lineending_checker;
+  term::StarndardDelimiterChecker std_delimiter;
+  term::WhitespaceChecker white_delimiter;
+  term::LineEndingChecker lineending_checker;
 
   unicode::UniString str;
   bool syntax_ok = false;
@@ -50,7 +89,7 @@ lexer::Lexeme* lexer::StringLexer::Lex(const unicode::UniString& string,
       break;
     }
 
-    if (lineending_checker(tmp, reader)) {
+    if (lineending_checker(tmp)) {
       while (!reader->IsEof() && (white_delimiter(tmp) || std_delimiter(tmp))) {
         reader->Read();
       }