OSDN Git Service

\90V\8bK\82É\8dì\90¬\82µ\82½TermLexer\82ð\97\98\97p\82µ\82Ä\93à\95\94\82ð\8fC\90³\82µ\82½\81B
authorU-C2007\Administrator <derutakayu@user.sourceforge.jp>
Wed, 6 Jan 2010 09:42:43 +0000 (18:42 +0900)
committerU-C2007\Administrator <derutakayu@user.sourceforge.jp>
Wed, 6 Jan 2010 09:42:43 +0000 (18:42 +0900)
src/lexer/string_lexer.cpp
src/lexer/string_lexer.h

index 2ed7081..d391c50 100755 (executable)
@@ -1,3 +1,4 @@
+#include <utility>
 #include "src/exception_macro.h"
 #include "src/lexer/string_lexer.h"
 #include "src/lexer/term_lexer.h"
@@ -11,6 +12,7 @@ namespace term = utakata::lexer::term;
 namespace reader = utakata::reader;
 namespace unicode = utakata::unicode;
 
+
 // 宣言のコメントを参照して下さい。
 bool lexer::EscapeLexer::Lex(reader::EncodingReader* reader,
                              unsigned int* code) {
@@ -21,41 +23,104 @@ bool lexer::EscapeLexer::Lex(reader::EncodingReader* reader,
 
   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;
+  }
 }
 
 // 文字列の終了地点は、同一行の`"`か、\\を含む複数行後の対応する`"`となります。
index c40e009..041487b 100755 (executable)
@@ -5,6 +5,7 @@
 #ifndef _UTAKATA_SRC_LEXER_STRING_LEXER_H_
 #define _UTAKATA_SRC_LEXER_STRING_LEXER_H_
 
+#include <map>
 #include "src/lexer/lexer_interface.h"
 
 namespace utakata {
@@ -20,6 +21,32 @@ class EncodingReader;
 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
@@ -41,6 +68,7 @@ class EscapeLexer {
   // エスケープシーケンスを判断する際に、判断基準とする読出
   // 文字数です。
   static const int kEscapeValidseLength = 2;
+
 public:
   EscapeLexer() {}
   virtual ~EscapeLexer() {}
@@ -61,9 +89,11 @@ public:
   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 {