OSDN Git Service

SchemeLexerの実装により、字句解析部分の作成を完了。
authorderui <derutakayu@user.sourceforge.jp>
Thu, 4 Feb 2010 14:49:13 +0000 (23:49 +0900)
committerderui <derutakayu@user.sourceforge.jp>
Thu, 4 Feb 2010 14:49:13 +0000 (23:49 +0900)
汎用二分木クラスへのテストを追加。

53 files changed:
Rakefile
Rakefile.in
autoscan-2.63.log [deleted file]
config.log
lib/binary_tree.h [new file with mode: 0755]
lib/debugutil.h [deleted file]
refactor_target/tree.h [deleted file]
src/lexer/boolean_lexer.cpp [changed mode: 0755->0644]
src/lexer/boolean_lexer.h [changed mode: 0755->0644]
src/lexer/charactor_lexer.cpp [changed mode: 0755->0644]
src/lexer/charactor_lexer.h [changed mode: 0755->0644]
src/lexer/comment_lexer.cpp [changed mode: 0755->0644]
src/lexer/comment_lexer.h [changed mode: 0755->0644]
src/lexer/identifier_lexer.cpp [changed mode: 0755->0644]
src/lexer/identifier_lexer.h [changed mode: 0755->0644]
src/lexer/inline_hex_escape_lexer.cpp [changed mode: 0755->0644]
src/lexer/inline_hex_escape_lexer.h [changed mode: 0755->0644]
src/lexer/inner_hex_lexer.cpp [changed mode: 0755->0644]
src/lexer/inner_hex_lexer.h [changed mode: 0755->0644]
src/lexer/lexeme_lexer.cpp [new file with mode: 0644]
src/lexer/lexeme_lexer.h [new file with mode: 0644]
src/lexer/lexeme_lexer_detail.h [new file with mode: 0644]
src/lexer/lexer_interface.h
src/lexer/number_lexer.cpp [changed mode: 0755->0644]
src/lexer/number_lexer.h [changed mode: 0755->0644]
src/lexer/scheme_lexer.cpp [new file with mode: 0644]
src/lexer/scheme_lexer.cpp.bk [deleted file]
src/lexer/scheme_lexer.h [changed mode: 0755->0644]
src/lexer/string_lexer.cpp [changed mode: 0755->0644]
src/lexer/string_lexer.h [changed mode: 0755->0644]
src/lexer/term_checker.cpp [changed mode: 0755->0644]
src/lexer/term_checker.h
src/lexer/term_lexer.h [changed mode: 0755->0644]
src/lexer/token.cpp [moved from src/lexeme.cpp with 50% similarity, mode: 0644]
src/lexer/token.h [moved from src/lexeme.h with 68% similarity, mode: 0644]
src/parser/parser.cpp.bk [moved from refactor_target/parser.cpp with 100% similarity]
src/parser/parser.h [moved from refactor_target/parser.h with 100% similarity]
src/parser/parser_handler.cpp.bk [moved from refactor_target/parser_handler.cpp with 100% similarity]
src/parser/parser_handler.h [moved from refactor_target/parser_handler.h with 100% similarity]
src/parser/parser_status.h [moved from refactor_target/parser_status.h with 100% similarity]
src/parser/syntax_tree.cpp [moved from refactor_target/tree.cpp with 100% similarity]
src/parser/syntax_tree.h [new file with mode: 0755]
test/binary_tree_test.cpp [new file with mode: 0755]
test/boolean_lexer_test.cpp
test/charactor_lexer_test.cpp
test/comment_lexer_test.cpp
test/datum_test.cpp [new file with mode: 0755]
test/identifier_lexer_test.cpp
test/lexeme_lexer_test.cpp [new file with mode: 0755]
test/lexer_test.cpp.bk [deleted file]
test/number_lexer_test.cpp
test/scheme_lexer_test.cpp [new file with mode: 0755]
test/string_lexer_test.cpp

index c592350..139fb01 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -27,12 +27,17 @@ TEST_PROGRAMS = TEST_SRCS.ext("")
 EXEEXT = ""
 
 # lists of clean objects
-CLEAN.include(OBJS, TEST_OBJECTS)
-CLEAN.include(".depend.mf")
+CLEAN.include(OBJS, TEST_OBJECTS, DEPS)
 CLOBBER.include(TEST_PROGRAMS)
 
-task "default" => ["compile"]
-task "test" => ["compile", "test_execute"]
+task "default" => ["depend_resolution", "compile"]
+task "test" => ["depend_resolution", "compile", "test_execute"]
+
+task "depend_resolution" => DEPS do |t|
+  t.prerequisites.each { |f|
+    import f.source
+  }
+end
 
 desc "Compile all sources "
 task "compile" => OBJS do |t|
@@ -52,23 +57,14 @@ rule '.o' => '.cpp' do |t|
   sh "#{CC} #{ldflags} #{cflags} #{includes} -c #{fullpath} -o #{t.name}"
 end
 
-# -MM による依存性の抽出を行います。既存の依存性については、
-file ".depend.mf" => SRCS do |t|
-  rm t.name if File.exists? t.name
-
-  t.prerequisites.each do |f|
-    depname = File.split(f)
-    depname[1] = File.basename(depname[1], ".cpp") + ".mf"
-    sh "#{CC} -MM -MF #{File.join(depname[0], depname[1])} #{ldflags} #{cflags} #{includes} #{f}"
-
-    replace_make_to_rake File.join(depname[0], depname[1]), t.name
-    # sh "cat #{File.join(depname[0], depname[1])} >> #{t.name}"
-    rm File.join(depname[0], depname[1])
-  end
+rule '.mf' => '.cpp' do |t|
+  fullpath = File.expand_path t.source
+  depname = File.split(t.source)
+  depname[1] = File.basename(depname[1], ".cpp") + ".mf"
+  sh "#{CC} -MM -MF #{File.join(depname[0], depname[1])} #{ldflags} #{cflags} #{includes} #{fullpath}"
+  import File.join(depname[0], depname[1])
 end
 
-import ".depend.mf"
-
 desc "run all test program in `TEST_PROGRAMS`"
 task :test_execute => TEST_PROGRAMS do |t|
   t.prerequisites.each { |f|
index ac9a5e5..8207ce3 100644 (file)
@@ -27,12 +27,17 @@ TEST_PROGRAMS = TEST_SRCS.ext("@EXEEXT@")
 EXEEXT = "@EXEEXT@"
 
 # lists of clean objects
-CLEAN.include(OBJS, TEST_OBJECTS)
-CLEAN.include(".depend.mf")
+CLEAN.include(OBJS, TEST_OBJECTS, DEPS)
 CLOBBER.include(TEST_PROGRAMS)
 
-task "default" => ["compile"]
-task "test" => ["compile", "test_execute"]
+task "default" => ["depend_resolution", "compile"]
+task "test" => ["depend_resolution", "compile", "test_execute"]
+
+task "depend_resolution" => DEPS do |t|
+  t.prerequisites.each { |f|
+    import f.source
+  }
+end
 
 desc "Compile all sources "
 task "compile" => OBJS do |t|
@@ -52,23 +57,14 @@ rule '.o' => '.cpp' do |t|
   sh "#{CC} #{ldflags} #{cflags} #{includes} -c #{fullpath} -o #{t.name}"
 end
 
-# -MM による依存性の抽出を行います。既存の依存性については、
-file ".depend.mf" => SRCS do |t|
-  rm t.name if File.exists? t.name
-
-  t.prerequisites.each do |f|
-    depname = File.split(f)
-    depname[1] = File.basename(depname[1], ".cpp") + ".mf"
-    sh "#{CC} -MM -MF #{File.join(depname[0], depname[1])} #{ldflags} #{cflags} #{includes} #{f}"
-
-    replace_make_to_rake File.join(depname[0], depname[1]), t.name
-    # sh "cat #{File.join(depname[0], depname[1])} >> #{t.name}"
-    rm File.join(depname[0], depname[1])
-  end
+rule '.mf' => '.cpp' do |t|
+  fullpath = File.expand_path t.source
+  depname = File.split(t.source)
+  depname[1] = File.basename(depname[1], ".cpp") + ".mf"
+  sh "#{CC} -MM -MF #{File.join(depname[0], depname[1])} #{ldflags} #{cflags} #{includes} #{fullpath}"
+  import File.join(depname[0], depname[1])
 end
 
-import ".depend.mf"
-
 desc "run all test program in `TEST_PROGRAMS`"
 task :test_execute => TEST_PROGRAMS do |t|
   t.prerequisites.each { |f|
diff --git a/autoscan-2.63.log b/autoscan-2.63.log
deleted file mode 100755 (executable)
index e69de29..0000000
index 34ea0ab..76ef1ab 100644 (file)
@@ -14,7 +14,7 @@ hostname = vaio_z
 uname -m = i686
 uname -r = 2.6.32-gentoo-r1
 uname -s = Linux
-uname -v = #2 SMP Wed Jan 13 20:45:37 JST 2010
+uname -v = #3 SMP Sat Jan 23 12:42:49 JST 2010
 
 /usr/bin/uname -p = Intel(R) Core(TM)2 Duo CPU P8800 @ 2.66GHz
 /bin/uname -X     = unknown
diff --git a/lib/binary_tree.h b/lib/binary_tree.h
new file mode 100755 (executable)
index 0000000..835560c
--- /dev/null
@@ -0,0 +1,21 @@
+// preorder、postorder、inorderのそれぞれの探索を利用できる、
+// 汎用二分木を提供します。
+// 汎用二分木では、以下の処理を行うことができます。
+// insert - 特定のNodeに対する値の設定
+// set_left - 左の葉に値を追加する。
+// set_right - 右の葉に値を追加する。
+// inorder_begin/end - 通りがけ順に探索するiteratorの開始・終了点を
+//                     指定します。
+// preorder_begin/end - 行きがけ順に探索するiteratorの開始・終了点を
+//                      返します。
+// postorder_begin/end - 帰り掛け順に探索するiteratorの開始・終了点を
+//                       返します。
+//
+// postorder/preorder/inorderは、それぞれテンプレート引数で
+// 指定することができます。デフォルトはinorderが指定されたことと同一です。
+#ifndef _UTAKATA_LIB_BINARY_TREE_H_
+#define _UTAKATA_LIB_BINARY_TREE_H_
+
+
+
+#endif /* _UTAKATA_LIB_BINARY_TREE_H_ */
diff --git a/lib/debugutil.h b/lib/debugutil.h
deleted file mode 100755 (executable)
index 918b78f..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef _DEBUGUTIL_H_
-#define _DEBUGUTIL_H_
-
-#include <algorithm>
-#include <iostream>                     // NOLINT
-#include <string>
-#include <functional>
-
-namespace utility {
-
-///////////////////////////////////////////////////////////////
-//  utakata内部で利用される、デバッグ用ユーティリティ。      //
-//  それぞれ、デバッグの際にのみ有効になるようになっており、 //
-//  DEBUG_がdefineされている場合は単なる空関数となる。       //
-///////////////////////////////////////////////////////////////
-
-template<class T>
-struct echo_iostream : std::unary_function<T, void> {
-  explicit echo_iostream(std::string delim) : delim_(delim) {}
-
-  void operator()(T t) {
-    std::cout << t << delim_;
-  }
-  std::string delim_;
-};
-
-template<class S>
-echo_iostream<typename S::value_type>
-get_echo_iostream(S type, std::string delim) {
-  return echo_iostream<typename S::value_type>(delim);
-}
-
-template<class S>
-echo_iostream<typename S::value_type> get_echo_iostream(S type) {
-  return echo_iostream<typename S::value_type>("");
-}
-
-template<class T>
-void echo_nl(T s) {
-  // 与えたデータを改行有で表示する。
-  echo_iostream<T>("\n")(s);
-}
-
-template<class T>
-void echo(T s) {
-  // 与えたデータをデリミタ無しで表示する。
-  echo_iostream<T>("")(s);
-}
-
-template<class T>
-void echo(T s, std::string d) {
-  echo_iostream<T> t(d);
-  t(s);
-}
-
-template<class T>
-void echoc_nl(const T& container_) {
-  // 渡されたコンテナの各要素をコンソールに出力する。引数が設定されている
-  // 場合には、改行無しで表示する。
-  std::string d = "\n";
-  std::for_each(container_.begin(), container_.end(),
-                get_echo_iostream(container_, d));
-}
-
-template<class T>
-void echoc_nl(T begin, T end) {
-  // 渡されたiteratorのbeginからendまでを標準出力に
-  // 出力する。
-  std::string d = "\n";
-  std::for_each(begin, end,
-                get_echo_iostream(begin, d));
-}
-
-
-template<class T>
-void echoc(const T& container_) {
-  // 渡されたコンテナの各要素をコンソールに出力する。引数が設定されている
-  // 場合には、改行無しで表示する。
-  std::for_each(container_.begin(), container_.end(),
-                get_echo_iostream(container_));
-}
-
-
-template<class T>
-void echoc(const T& container_, std::string delim) {
-  // containerの各要素をdelimで区切って表示する。
-  // delimを指定しない場合、一切区切らずに表示される。
-  std::for_each(container_.begin(), container_.end(),
-                get_echo_iostream(container_, delim));
-}
-
-template<class T>
-void echoc(T begin, T end, std::string delim) {
-  // 渡されたiteratorのbeginからendまでを標準出力に
-  // 出力する。
-
-  std::for_each(begin, end,
-                get_echo_iostream(begin, delim));
-}
-}  //  end of namespace debugutil
-
-#endif /* _DEBUGUTIL_H_ */
diff --git a/refactor_target/tree.h b/refactor_target/tree.h
deleted file mode 100755 (executable)
index 4b1e0dd..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef _TREE_H_
-#define _TREE_H_
-
-#include "smart_ptr.h"
-#include <utility>              // std::pair
-#include <vector>
-
-namespace utakata {
-
-    namespace unicode {
-    
-        class UniString;
-    
-    };
-
-    namespace literal {
-    
-        struct LiteralData;
-        class Literal;
-    
-    };
-
-    namespace lexeme {
-        class LexemeID;
-    };
-
-    namespace syntax {
-
-        class DatumID;
-        class Tree
-        {
-            // Scheme の構文データを表す Tree を返す。
-            // 内部的には、殆ど実体そのままの cons を構成する。
-            // ただし、構成している cons の内容としては、 datum でしか無い
-            // ため、そのあたりが多少異なる。内部での実装は、次のように
-            // なる。
-            // lexeme datum -> node_pair::first = literal node_pair::second = literal::literal
-            // compound datum -> node_pair::first = list, vector, bytevector node_pair::second = NULL
-            // abbreviation -> node_pair::first = abbreviation, node_pair::second = literal::Literal
-            // また、 lexeme datum は、 car,cdr それぞれが存在しておらず、
-            // node_pair の second が設定されるのみとなる。
-            // また、 iterator 及び iterator の ++ による各要素の巡回を行なうことができる。
-            // iterator 中で、 nil と判断されたデータについては、その時点で
-            // 巡回が停止される。
-            // 空リスト≠ nil である。 nil はあくまで syntax tree の終端を示すためだけの
-            // 特別な datum であり、外部にこの定義が漏れることはない。
-            // 空リストは、「 car,cdr がそれぞれ isNull == true である datumid = list 」である
-            // cons が対象となる。
-
-            typedef std::pair<DatumID, smart_ptr<literal::Literal> > node_pair;
-            // 実装でのみ定義される。
-            struct TreeNode;
-
-        public:
-
-            class iterator
-            {
-            public:
-                // ツリーを巡回し、そのノードの literal を取得することを可能とする。
-                iterator ();
-                iterator (const iterator& s);
-                
-                ~iterator () {}
-
-                iterator& operator=(const iterator& rh);
-                iterator& operator++ ();
-                node_pair& operator*();
-                node_pair* operator->();
-
-                // 一致するかどうかを返す
-                bool operator==(const iterator& rh);
-                bool operator!=(const iterator& rh) {
-                    return ! (*this == rh);
-                }
-
-                // 現在位置を表すiterator
-                std::vector<smart_ptr<TreeNode> >::iterator current_;
-
-            private:
-
-                void swap (const iterator& s);
-
-            };
-
-            
-        public:
-
-            Tree ();
-            virtual ~Tree () {}
-
-            // 現在の Tree の先頭=root node と、 end = 次に指す場所が存在しない
-            // node を返す。
-            iterator begin ();
-            iterator end ();
-
-            // push_backによって追加を行う。
-            void push_back (node_pair datum);
-            void push_back (iterator b, iterator e, node_pair datum);
-
-            // itが指すnodeの内部listの先頭を返す。
-            iterator in_compound_begin(iterator it);
-            iterator in_compound_end(iterator it);
-
-            size_t size() const {return node_.size();}
-
-        private:
-
-            std::vector<smart_ptr<TreeNode> > node_;
-
-        };
-
-        // 渡した iterator が list datum であるかどうかを返す。
-        bool isCompoundDatum (Tree::iterator node);
-
-        // 渡した node が literal であるかどうかを返す。
-        bool isLiteral (Tree::iterator node);
-
-        // 各 datum を表す std::pair を作成するためのヘルパ関数。
-        std::pair<DatumID, smart_ptr<literal::Literal> > makeCompoundDatum (
-            DatumID id);
-        
-        std::pair<DatumID, smart_ptr<literal::Literal> > makeNilList ();
-        std::pair<DatumID, smart_ptr<literal::Literal> > makeLexemeDatum (smart_ptr<literal::Literal> l,
-            DatumID id);
-        std::pair<DatumID, smart_ptr<literal::Literal> > makeAbbreviation (smart_ptr<literal::Literal> l);
-
-        // 渡したtreeの内容を文字列に変換する。
-//        smart_ptr<unicode::UniString> treeToValue(Tree& t);
-    };
-
-};
-
-#endif /* _TREE_H_ */
old mode 100755 (executable)
new mode 100644 (file)
index 2fb47c3..460c285
@@ -2,7 +2,7 @@
 
 #include "src/encoding_reader.h"
 #include "src/exception_macro.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/lexer/boolean_lexer.h"
 #include "src/lexer/term_lexer.h"
 #include "src/lexer/term_checker.h"
@@ -14,11 +14,11 @@ namespace unicode = utakata::unicode;
 namespace reader = utakata::reader;
 
 // 宣言のコメントを参照してください。
-lexer::Lexeme* lexer::BooleanLexer::Lex(reader::EncodingReader* reader) {
+akebono::smart_ptr<lexer::Token> lexer::BooleanLexer::Lex(reader::EncodingReader* reader) {
 
   lexer::TermLexer<term::Boolean> boolean;
   if (!boolean.CheckToken(reader)) {
-    return NULL;
+    return akebono::smart_ptr<lexer::Token>();
   }
 
   unicode::UniString str(unicode::Convert(
@@ -31,5 +31,6 @@ lexer::Lexeme* lexer::BooleanLexer::Lex(reader::EncodingReader* reader) {
     THROW_EXCEPTION_(lexer::LexException, except_message);
   }
 
-  return new lexer::Lexeme(str, lexer::Lexeme::kBoolean);
+  return akebono::smart_ptr<lexer::Token>(
+      new lexer::Token(str, lexer::Token::kBoolean));
 }
old mode 100755 (executable)
new mode 100644 (file)
index 680748e..66cf8c2
@@ -17,7 +17,7 @@ class EncodingReader;
 }
 
 namespace lexer {
-class Lexeme;
+class Token;
 
 // Scheme構文におけるboolean値の字句解析を行います。
 // Scheme構文におけるbooleanリテラルは以下の通りです。
@@ -26,10 +26,10 @@ class Lexeme;
 class BooleanLexer : public IPartOfLexer {
  public:
   // 読出しストリームへのポインタを受け取って、結果として生成した
-  // Lexemeクラスを返します。
+  // Tokenクラスを返します。
   // booleanのの字句として異常である文字列であった場合、LexException例外が
   // 送出されます。
-  virtual Lexeme* Lex(reader::EncodingReader* reader);
+  virtual akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
 };
 
 class BooleanLexerFactory : public ILexerCreator {
old mode 100755 (executable)
new mode 100644 (file)
index aa946b7..d026508
@@ -3,7 +3,7 @@
 
 #include "src/encoding_reader.h"
 #include "src/exception_macro.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/lexer/charactor_lexer.h"
 #include "src/lexer/term_lexer.h"
 #include "src/lexer/term_checker.h"
@@ -70,10 +70,10 @@ void lexer::CharactorNameLexer::InitializeCharactorMap() {
 std::string lexer::CharactorLexer::kCharactorStart = std::string("#\\");
 
 // 宣言のコメントを参照してください。
-lexer::Lexeme* lexer::CharactorLexer::Lex(reader::EncodingReader* reader) {
+akebono::smart_ptr<lexer::Token> lexer::CharactorLexer::Lex(reader::EncodingReader* reader) {
   unicode::UniString tmp(unicode::Convert(reader->Peek(2)));
   if (tmp != unicode::Convert(kCharactorStart)) {
-    return NULL;
+    return akebono::smart_ptr<lexer::Token>();
   }
   reader->Read(2);
 
@@ -96,8 +96,9 @@ lexer::Lexeme* lexer::CharactorLexer::Lex(reader::EncodingReader* reader) {
   unicode::UniChar parsed_charactor;
   ConvertStringToCharactor(str, &parsed_charactor);
 
-  return new lexer::Lexeme(unicode::UniString(parsed_charactor, 1),
-                           lexer::Lexeme::kCharactor);
+  return akebono::smart_ptr<lexer::Token>(
+      new lexer::Token(unicode::UniString(parsed_charactor, 1),
+                       lexer::Token::kCharactor));
 }
 
 // 宣言のコメントを参照してください。
old mode 100755 (executable)
new mode 100644 (file)
index 2795b22..9bd40da
@@ -19,7 +19,7 @@ class EncodingReader;
 }
 
 namespace lexer {
-class Lexeme;
+class Token;
 
 // Schemeの文字名に関係する処理及び定数をまとめたクラスです。
 // このクラスにて文字名として処理を行う文字列は以下の通りです。
@@ -81,11 +81,11 @@ class CharactorLexer : public IPartOfLexer {
   virtual ~CharactorLexer() {}
 
   // 読出しストリームへのポインタを受け取って、結果として生成した
-  // Lexemeクラスを返します。
+  // Tokenクラスを返します。
   // Charactorの字句として異常である文字列であった場合、LexException例外が
   // 送出されます。
   // Charactorの開始記号が見つからない場合、NULLが返されます。
-  virtual Lexeme* Lex(reader::EncodingReader* reader);
+  virtual akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
  private:
 
   // 渡されたUniStringに対して、対応する文字コードを返します。
old mode 100755 (executable)
new mode 100644 (file)
index f3cad0b..166c0a5
@@ -1,7 +1,7 @@
 #include <algorithm>
 
 #include "src/exception_macro.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/lexer/comment_lexer.h"
 #include "src/lexer/lexer_interface.h"
 #include "src/lexer/term_lexer.h"
@@ -42,26 +42,33 @@ bool lexer::detail::NestedLexer::Lex(reader::EncodingReader* reader) {
 }
 
 // 宣言のコメントを参照してください。
-lexer::Lexeme* lexer::CommentLexer::Lex(reader::EncodingReader* reader) {
+bool lexer::CommentLexer::Lex(reader::EncodingReader* reader,
+                              akebono::smart_ptr<lexer::Token>& result) {
   lexer::TermLexer<term::DatumComment> datum_comment;
   lexer::TermLexer<term::SpecialComment> special_comment;
 
   unicode::UniChar ch(reader->Peek());
   if (ch.rawcode() == ';') {
     SkipByLineComment(reader);
+    return true;
 
   } else if (datum_comment.CheckToken(reader)) {
     reader->Read(datum_comment.previous_read_size());
-    return new lexer::Lexeme(unicode::UniString(), lexer::Lexeme::kDatumComment);
+    result.reset(new lexer::Token(unicode::UniString(),
+                                  lexer::Token::kDatumComment));
+    return true;
 
   } else if (special_comment.CheckToken(reader)) {
     reader->Read(special_comment.previous_read_size());
-    return new lexer::Lexeme(unicode::UniString(), lexer::Lexeme::kSpecialComment);
-  } else {
-    lexer::detail::NestedLexer().Lex(reader);
+    result.reset(new lexer::Token(unicode::UniString(),
+                                  lexer::Token::kSpecialComment));
+    return true;
+
+  } else if (lexer::detail::NestedLexer().Lex(reader)) {
+    return true;
   }
 
-  return NULL;
+  return false;
 }
 
 // ; の発見時点でこの関数が呼ばれるため、内部で先頭の一文字を
old mode 100755 (executable)
new mode 100644 (file)
index e7c222c..673a629
@@ -4,7 +4,7 @@
 #ifndef _UTAKATA_SRC_LEXER_COMMENT_LEXER_H_
 #define _UTAKATA_SRC_LEXER_COMMENT_LEXER_H_
 
-#include "src/lexer/lexer_interface.h"
+#include "lib/smart_ptr.h"
 
 namespace utakata {
 namespace reader {
@@ -13,6 +13,7 @@ class EncodingReader;
 
 namespace lexer {
 
+class Token;
 namespace detail {
 
 // #| と |#に囲まれた領域をコメントとして読み飛ばします。
@@ -26,19 +27,20 @@ class NestedLexer {
 };
 }
 
-class Lexeme;
 // <comment>に一致する字句を解釈する機能を提供します。
-class CommentLexer : public IPartOfLexer {
+class CommentLexer {
  public:
 
   // readerの先頭から、<comment>に一致するかどうかを返却します。
   // <nested comment>、及び;より開始されるコメントについては、
-  // 当該部分が読み飛ばされた上で、NULLが返却されますが、
+  // 当該部分が読み飛ばされた上で、trueが返却されます。
+  // その場合、resultに対しては何も行いません。
   // #; <interlexeme space> <datum>、また#!<identifier>については、
-  // それぞれ個別のLexemeが返却されます。
-  // Parserは、受け取ったLexemeに対して処理を行うことができますが、
+  // それぞれ個別のTokenが返却されます。
+  // Parserは、受け取ったTokenに対して処理を行うことができますが、
   // コメントが必ず読み飛ばされることを保証しなければなりません。
-  lexer::Lexeme* Lex(reader::EncodingReader* reader);
+  bool Lex(reader::EncodingReader* reader,
+           akebono::smart_ptr<lexer::Token>& result);
 
  private:
 
old mode 100755 (executable)
new mode 100644 (file)
index d782c4c..dddf59f
@@ -3,7 +3,7 @@
 #include "src/lexer/term_lexer.h"
 #include "src/lexer/term_checker.h"
 #include "src/lexer/inline_hex_escape_lexer.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/encoding_reader.h"
 #include "src/unicode.h"
 
@@ -112,16 +112,17 @@ bool lexer::detail::PeculiarIdentifierLexer::Lex(reader::EncodingReader* reader,
 }
 
 // 宣言のコメントを参照してください。
-lexer::Lexeme* lexer::IdentifierLexer::Lex(reader::EncodingReader* reader) {
+akebono::smart_ptr<lexer::Token> lexer::IdentifierLexer::Lex(reader::EncodingReader* reader) {
   lexer::detail::PeculiarIdentifierLexer peculiar_ident;
   lexer::detail::InitialLexer initial;
 
   unicode::UniString identifier;
   if (peculiar_ident.Lex(reader, &identifier)) {
-      return new lexer::Lexeme(identifier, lexer::Lexeme::kIdentifier);
+    return akebono::smart_ptr<lexer::Token>(
+        new lexer::Token(identifier, lexer::Token::kIdentifier));
   } else {
     if (!initial.Lex(reader, &identifier)) {
-      return false;
+      return akebono::smart_ptr<lexer::Token>();
     }
 
     lexer::detail::SubsequenceLexer subseq;
@@ -141,5 +142,6 @@ lexer::Lexeme* lexer::IdentifierLexer::Lex(reader::EncodingReader* reader) {
     }
   }
 
-  return new lexer::Lexeme(identifier, lexer::Lexeme::kIdentifier);
+  return akebono::smart_ptr<lexer::Token>(
+      new lexer::Token(identifier, lexer::Token::kIdentifier));
 }
old mode 100755 (executable)
new mode 100644 (file)
index 2083392..e34dce7
@@ -1,6 +1,6 @@
 // Scheme構文における識別子を判別するLexerを定義します。
 // ここで定義されるLexerは、IPartOfLexerから派生しており、字句要素
-// Lexemeを返却します。
+// Tokenを返却します。
 #ifndef _UTAKATA_SRC_LEXER_IDENTIFIER_LEXER_H_
 #define _UTAKATA_SRC_LEXER_IDENTIFIER_LEXER_H_
 
@@ -19,7 +19,7 @@ class EncodingReader;
 }
 
 namespace lexer {
-class Lexeme;
+class Token;
 
 namespace detail {
 class SubsequenceLexer {
@@ -75,9 +75,9 @@ class IdentifierLexer : public IPartOfLexer {
   virtual ~IdentifierLexer() {}
 
   // 読出しストリームへのポインタを受け取って、結果として生成した
-  // Lexemeのポインタを返します。
+  // Tokenのポインタを返します。
   // 文字列の字句では無い場合、NULLが返却されます。
-  virtual Lexeme* Lex(reader::EncodingReader* reader);
+  virtual akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
 };
 
 class IdentifierLexerFactory : public ILexerCreator {
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/src/lexer/lexeme_lexer.cpp b/src/lexer/lexeme_lexer.cpp
new file mode 100644 (file)
index 0000000..479891a
--- /dev/null
@@ -0,0 +1,99 @@
+#include <algorithm>
+
+#include "src/encoding_reader.h"
+#include "src/exception_macro.h"
+#include "src/lexer/token.h"
+#include "src/lexer/lexeme_lexer.h"
+#include "src/lexer/lexeme_lexer_detail.h"
+#include "src/lexer/term_checker.h"
+#include "src/lexer/term_lexer.h"
+#include "src/unicode.h"
+
+namespace lexer = utakata::lexer;
+namespace term = utakata::lexer::term;
+namespace unicode = utakata::unicode;
+namespace reader = utakata::reader;
+
+// unsyntax, unsyntaxsplicing 間における最長一致に基づいて順序を設定しています。
+lexer::LexemeLexer::LexemeLexer() : term_binders_() {
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::OpenParenthesis>(
+          lexer::Token::kOpenParenthesis));
+
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::CloseParenthesis>(
+          lexer::Token::kCloseParenthesis));
+
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::OpenBracket>(
+          lexer::Token::kOpenBracket));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::CloseBracket>(
+          lexer::Token::kCloseBracket));
+
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Dot>(
+          lexer::Token::kDot));
+
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::OpenVector>(
+          lexer::Token::kVector));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::OpenByteVector>(
+          lexer::Token::kByteVector));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Quote>(
+          lexer::Token::kQuote));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Quasiquote>(
+          lexer::Token::kQuasiquote));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::UnquoteSplicing>(
+          lexer::Token::kUnquoteSplicing));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Unquote>(
+          lexer::Token::kUnquote));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Syntax>(
+          lexer::Token::kSyntax));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Quasisyntax>(
+          lexer::Token::kQuasisyntax));
+
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::UnsyntaxSplicing>(
+          lexer::Token::kUnsyntaxSplicing));
+  term_binders_.push_back(
+      new lexer::detail::LexemeTermBinder<term::Unsyntax>(
+          lexer::Token::kUnsyntax));
+}
+
+// 内部でのみ利用するデータですので、直接deleteを行います。
+lexer::LexemeLexer::~LexemeLexer() {
+  std::vector<lexer::detail::LexemeTermBinderBase*>::iterator it = term_binders_.begin(),
+      end = term_binders_.end();
+  for (; it != end; ++it) {
+    delete *it;
+  }
+}
+
+// 各非終端記号については、それぞれのLexerの結果をそのまま返却します。
+// 例外はLexemeLexer中では補足しません。
+akebono::smart_ptr<lexer::Token> lexer::LexemeLexer::Lex(reader::EncodingReader* reader) {
+
+  akebono::smart_ptr<lexer::Token> result_token(LexTermOfLexeme(reader));
+  return result_token;
+}
+
+// 内部で作成されたTokenは、呼び出し元で補足されます。
+akebono::smart_ptr<lexer::Token> lexer::LexemeLexer::LexTermOfLexeme(
+    reader::EncodingReader* reader) {
+  std::vector<lexer::detail::LexemeTermBinderBase*>::iterator it =
+      akebono::range::find_if(term_binders_,
+                              lexer::detail::LexemeTermChekcer(reader));
+  if (it == term_binders_.end()) {
+    return akebono::smart_ptr<lexer::Token>();
+  }
+
+  return (*it)->result();
+}
diff --git a/src/lexer/lexeme_lexer.h b/src/lexer/lexeme_lexer.h
new file mode 100644 (file)
index 0000000..d00c580
--- /dev/null
@@ -0,0 +1,75 @@
+// Scheme字句構文中において、<token>に該当する字句を解析して返却する
+// 機能を提供します。
+// <token>に一致する字句構文は以下の通りです。
+// <token> - <identifier> | <boolean> | <number>
+//          | <character> | <string>
+//          | ( | ) | [ | ] | #( | #vu8( | ' | `  | , | ,@ | .
+//          | #' | #` | #, | #,@
+// 非終端記号については、それぞれに対応したLexerによって解析が行われます。
+#ifndef _UTAKATA_SRC_LEXER_LEXEME_LEXER_H_
+#define _UTAKATA_SRC_LEXER_LEXEME_LEXER_H_
+
+
+
+#include <vector>
+#include "src/lexer/lexer_interface.h"
+
+namespace utakata {
+namespace unicode {
+class UniString;
+}
+
+namespace reader {
+class EncodingReader;
+}
+
+namespace lexer {
+
+namespace detail {
+class LexemeTermBinderBase;
+}
+
+class Token;
+
+// Scheme字句構文における<token>中の終端記号に該当する字句を解析して返却する機能を
+// 提供します。
+class LexemeLexer : public IPartOfLexer {
+ public:
+
+  // 内部で利用するTermBinderを定義します。
+  LexemeLexer();
+
+  // TermBinder内部の各TermBinderをdeleteします。
+  ~LexemeLexer();
+
+  // readerの先頭から、<token>に一致する字句を解析して、それぞれのToken
+  // として返却します。
+  // <token>に一致する構文が存在しない場合、NULLが返却されます。
+  // 返却された有効なTokenは、利用する側に解体責任が発生します。
+  virtual akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
+
+ private:
+
+  // readerの先頭から、<token>中の終端記号にマッチするかどうかをチェック
+  // し、結果を返却します。
+  // それぞれに一致しない場合、NULLを返却します。
+  akebono::smart_ptr<lexer::Token> LexTermOfLexeme(reader::EncodingReader* reader);
+
+  // 内部で利用されるTermBinder群です。コンストラクタで初期化されます。
+  std::vector<lexer::detail::LexemeTermBinderBase*> term_binders_;
+};
+
+class LexemeLexerFactory : public ILexerCreator {
+  // LexemeLexerをIPartOfLexerとして生成するファクトリです。
+ public:
+  LexemeLexerFactory() {}
+  virtual ~LexemeLexerFactory() {}
+
+  // ChractorLexerを新たに割り当てて返します。
+  // 返されたインスタンスは、取得側で開放する必要があります。
+  virtual IPartOfLexer* Create() const {return new LexemeLexer();}
+};
+}
+}
+
+#endif /* _UTAKATA_SRC_LEXER_LEXEME_LEXER_H_ */
diff --git a/src/lexer/lexeme_lexer_detail.h b/src/lexer/lexeme_lexer_detail.h
new file mode 100644 (file)
index 0000000..3260841
--- /dev/null
@@ -0,0 +1,86 @@
+// utakata::lexer::LexemeLexer内の実装にのみ利用されるクラス、テンプレート
+// を提供します。
+// このファイルでは、以下を提供します。
+// 
+// LexemeTermBinder - Termから、Lexemeを生成するテンプレートクラスです。
+//                    このクラスはLexemeTermBinderBaseから派生しています。
+// 
+#ifndef _UTAKATA_SRC_LEXER_LEXEME_LEXER_DETAIL_H_
+#define _UTAKATA_SRC_LEXER_LEXEME_LEXER_DETAIL_H_
+
+#include "lib/smart_ptr.h"
+
+namespace utakata {
+namespace unicode {
+class UniString;
+}
+
+namespace reader {
+class EncodingReader;
+}
+
+namespace lexer {
+
+class Token;
+namespace detail {
+
+// LexemeTermBinderを実行します。実行のためにreaderを取得しますが、それ以外
+// の動作は行いません。
+struct LexemeTermChekcer {
+  LexemeTermChekcer(reader::EncodingReader* reader) : reader_(reader) {}
+
+  // 渡されたTのoperator()を実行します。
+  template <typename T>
+  bool operator()(T& it) {
+    return (*it)(reader_);
+  }
+
+  reader::EncodingReader* reader_;
+};
+
+// Term単体をLexemeとして利用するためのbinderとして働きます。
+// 実際には、LexemeTermBinderを利用します。
+struct LexemeTermBinderBase {
+  virtual bool operator()(reader::EncodingReader* reader) = 0;
+
+  virtual akebono::smart_ptr<lexer::Token> result() = 0;
+};
+
+template <typename T>
+struct LexemeTermBinder : public LexemeTermBinderBase {
+  LexemeTermBinder(Token::TokenType type) : type_(type), result_() {}
+
+  // 渡されたreaderから、Termに一致するかどうかをチェックし、結果を返却します。
+  // T()がfalseを返却する場合、NULLを返します。
+  bool operator()(reader::EncodingReader* reader) {
+    namespace lexer = utakata::lexer;
+    unsigned int read_size = 0;
+    if (T()(reader, &read_size)) {
+      result_.reset(
+          new lexer::Token(unicode::Convert(reader->Read(read_size)),
+                           type_));
+      return true;
+    }
+    result_.release();
+    return false;
+  }
+
+  akebono::smart_ptr<lexer::Token> result() {
+    return result_;
+  }
+
+ private:
+
+  // Tとして渡されるTermと結びつけられるTokenTypeです。
+  lexer::Token::TokenType type_;
+
+  // 結果として作成されるTokenです。operator()がfalseを返した時、
+  // NULLに初期化されます。
+  akebono::smart_ptr<lexer::Token> result_;
+};
+
+} // end of detail
+}
+}
+
+#endif /* _UTAKATA_SRC_LEXER_LEXEME_LEXER_DETAIL_H_ */
index 81ac696..91b0289 100644 (file)
@@ -5,7 +5,7 @@
 // 記述したLexerDispatchTermを返します。
 // ILexerCreatorは、IPartsOfLexerと1:1で対応していなければなりません。
 //
-// IPartsOfLexerは、実際に字句解析を行います。解析結果として、ILexeme
+// IPartsOfLexerは、実際に字句解析を行います。解析結果として、IToken
 // 返すようにします。
 #ifndef _UTAKATA_SRC_LEXER_INTERFACE_H_
 #define _UTAKATA_SRC_LEXER_INTERFACE_H_
@@ -13,6 +13,7 @@
 #include <string>
 #include <map>
 #include "src/exception.h"
+#include "lib/smart_ptr.h"
 
 namespace utakata {
 
@@ -25,7 +26,7 @@ class EncodingReader;
 };
 
 namespace lexer {
-class Lexeme;
+class Token;
 class LexException : public exception::Exception {
   // 字句解析時に発生した例外を送出します。
  public:
@@ -44,16 +45,16 @@ class LexException : public exception::Exception {
 class IPartOfLexer {
   // 各非終端記号の字句解析を行うクラスのインターフェースです。
   // IPartOfLexerを継承したクラスは、Lexメソッドを実装する必要があります。
-  // Lexは必ずLexemeを新規に生成して返す必要があります。
+  // Lexは必ずTokenを新規に生成して返す必要があります。
  public:
   virtual ~IPartOfLexer() {}
 
   // 読出しストリームへのポインタを受け取り、指定されたトークンを読み出し、
-  // Lexemeを生成して返却します。
+  // Tokenを生成して返却します。
   // 読み出し条件が成立しない場合にはNULLを返し、字句が完全に読み出せた
-  // 場合には、生成したLexemeへのポインタを返却しなければなりません。
+  // 場合には、生成したTokenへのポインタを返却しなければなりません。
   // 字句解析がエラーの場合には、LexException例外を発生させなければなりません。
-  virtual Lexeme* Lex(reader::EncodingReader* stream) = 0;
+  virtual akebono::smart_ptr<Token> Lex(reader::EncodingReader* stream) = 0;
 };
 
 class ILexerCreator {
old mode 100755 (executable)
new mode 100644 (file)
index 41603d6..077d701
@@ -1,4 +1,4 @@
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/exception_macro.h"
 #include "src/encoding_reader.h"
 #include "src/lexer/term_checker.h"
@@ -162,7 +162,7 @@ bool lexer::detail::DecimalLexer::InnerLexFloating(
 
 // <number>の字句要素を解釈します。解釈されない場合、NULLが返されます。
 // 字句構文違反があった場合、LexException例外が発生します。
-lexer::Lexeme* lexer::NumberLexer::Lex(reader::EncodingReader* reader) {
+akebono::smart_ptr<lexer::Token> lexer::NumberLexer::Lex(reader::EncodingReader* reader) {
   lexer::detail::NumLexer<2> binary;
   lexer::detail::NumLexer<8> oct;
   lexer::detail::NumLexer<10> decimal;
@@ -170,14 +170,21 @@ lexer::Lexeme* lexer::NumberLexer::Lex(reader::EncodingReader* reader) {
 
   unicode::UniString number_string;
   if (binary.Lex(reader, &number_string)) {
-    return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
+    return akebono::smart_ptr<lexer::Token>(
+        new lexer::Token(number_string, lexer::Token::kNumber));
+
   } else if (oct.Lex(reader, &number_string)) {
-    return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
+    return akebono::smart_ptr<lexer::Token>(
+        new lexer::Token(number_string, lexer::Token::kNumber));
+
   } else if (decimal.Lex(reader, &number_string)) {
-    return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
+    return akebono::smart_ptr<lexer::Token>(
+        new lexer::Token(number_string, lexer::Token::kNumber));
+
   } else if (hex.Lex(reader, &number_string)) {
-    return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
+    return akebono::smart_ptr<lexer::Token>(
+        new lexer::Token(number_string, lexer::Token::kNumber));
   }
 
-  return NULL;
+  return akebono::smart_ptr<lexer::Token>();
 }
old mode 100755 (executable)
new mode 100644 (file)
index 10e42c6..bac3e77
@@ -1,13 +1,13 @@
 //
 // Schemeの数値項目に対する限定的な字句解析器を定義します。
 // NumberLexerは、StreamReaderより該当する分のデータを取得し、
-// 結果としてlexeme::Numberを返します。
+// 結果としてtoken::Numberを返します。
 //
 // example
 // -------
 // NumberLexer l();
 // StreamReader r();    // in text "+1.022"
-// smart_ptr<ILexeme> o = l.lex(r);
+// smart_ptr<IToken> o = l.lex(r);
 //
 #ifndef _NUMBER_LEXER_H_
 #define _NUMBER_LEXER_H_
@@ -71,14 +71,14 @@ class DecimalLexer {
 };
 } // end of detail
 
-class Lexeme;
+class Token;
 
 // <number>に一致する字句を読出すためのLexerです。IPartOfLexerを継承している
-// ため、このLexerは、該当するLexemeを返す必要があります。
+// ため、このLexerは、該当するTokenを返す必要があります。
 class NumberLexer : public IPartOfLexer {
  public:
   virtual ~NumberLexer() {}
-  virtual Lexeme* Lex(reader::EncodingReader* reader);
+  virtual akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
 };
 } // end of lexer
 } // end of utakata
diff --git a/src/lexer/scheme_lexer.cpp b/src/lexer/scheme_lexer.cpp
new file mode 100644 (file)
index 0000000..f97060e
--- /dev/null
@@ -0,0 +1,89 @@
+#include "lib/smart_ptr.h"
+#include "src/encoding_reader.h"
+#include "src/lexer/term_lexer.h"
+#include "src/lexer/term_checker.h"
+#include "src/lexer/boolean_lexer.h"
+#include "src/lexer/comment_lexer.h"
+#include "src/lexer/charactor_lexer.h"
+#include "src/lexer/identifier_lexer.h"
+#include "src/lexer/lexeme_lexer.h"
+#include "src/lexer/number_lexer.h"
+#include "src/lexer/scheme_lexer.h"
+#include "src/lexer/string_lexer.h"
+#include "src/lexer/token.h"
+#include "src/unicode.h"
+
+namespace lexer = utakata::lexer;
+namespace reader = utakata::reader;
+namespace unicode = utakata::unicode;
+
+lexer::SchemeLexer::SchemeLexer() : inner_lexers_() {
+  inner_lexers_.push_back(akebono::smart_ptr<lexer::IPartOfLexer>(
+      new lexer::IdentifierLexer()));
+
+  inner_lexers_.push_back(akebono::smart_ptr<lexer::IPartOfLexer>(
+      new lexer::StringLexer()));
+
+  inner_lexers_.push_back(akebono::smart_ptr<lexer::IPartOfLexer>(
+      new lexer::NumberLexer()));
+
+  inner_lexers_.push_back(akebono::smart_ptr<lexer::IPartOfLexer>(
+      new lexer::CharactorLexer()));
+
+  inner_lexers_.push_back(akebono::smart_ptr<lexer::IPartOfLexer>(
+      new lexer::BooleanLexer()));
+
+  inner_lexers_.push_back(akebono::smart_ptr<lexer::IPartOfLexer>(
+      new lexer::LexemeLexer()));
+}
+
+// 各カテゴリのチェック関数を利用して、readerから文字列を読出して、Tokenを
+// 返します。
+// Lexerは、原則として最長一致したTokenを返します。
+// また、内部では不要なinterlexeme spaceの読み飛ばしを最初に行います。
+// ただし、interlexeme spaceの読み飛ばし時点で、DatumCommentが存在した
+// 場合、その時点で返却が行われます。
+akebono::smart_ptr<lexer::Token> lexer::SchemeLexer::Lex(
+    reader::EncodingReader* reader) {
+  if (reader->IsEof()) {
+    return akebono::smart_ptr<lexer::Token>(
+        new lexer::Token(unicode::UniString(), lexer::Token::kEOS));
+  }
+
+  akebono::smart_ptr<lexer::Token> result(SkipInterLexemeSpace(reader));
+  if (!result.is_null()) {
+    return result;
+  }
+
+  // 限定的にnewを利用しています。利用される場合、このまま返却が行われます。
+  std::vector<akebono::smart_ptr<lexer::IPartOfLexer> >::iterator it =
+      akebono::range::find_if(inner_lexers_,
+                              lexer::detail::GetToken(reader, result));
+  if (it == inner_lexers_.end()) {
+    return akebono::smart_ptr<lexer::Token>();
+  }
+
+  return result;
+}
+
+// <interlexeme space>は、<whitespace>または<comment>の0個以上の連続した
+// データとなります。
+akebono::smart_ptr<lexer::Token> lexer::SchemeLexer::SkipInterLexemeSpace(
+    reader::EncodingReader* reader) {
+  lexer::TermLexer<term::Whitespace> whitespace;
+  lexer::CommentLexer comment;
+
+  akebono::smart_ptr<lexer::Token> result;
+  while (!reader->IsEof()) {
+    if (whitespace.CheckToken(reader)) {
+      reader->Read(whitespace.previous_read_size());
+    } else if (comment.Lex(reader, result)) {
+      if (!result.is_null()) {
+        break;
+      }
+    } else {
+      break;
+    }
+  }
+  return result;
+}
diff --git a/src/lexer/scheme_lexer.cpp.bk b/src/lexer/scheme_lexer.cpp.bk
deleted file mode 100644 (file)
index 3d93a88..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "src/encoding_reader.h"
-#include "src/lexer/scheme_lexer.h"
-#include "src/unicode.h"
-
-namespace lexer = utakata::lexer;
-namespace reader = utakata::reader;
-namespace unicode = utakata::unicode;
-
-lexer::Token::Token(const unicode::UniString& string_, lexer::TokenType type_)
-    : string(new unicode::UniString(string_)), type(type_) {}
-
-// 宣言のコメントを参照してください。
-lexer::RestrictiveLexer::RestrictiveLexer() {}
-
-// 各カテゴリのチェック関数を利用して、readerから文字列を読出して、Tokenを
-// 返します。
-// Lexerは、原則として最長一致したTokenを返します。
-lexer::Token* lexer::RestrictiveLexer::Lex(reader::EncodingReader* reader) {
-  if (reader->IsEof()) {
-    return new Token(unicode::UniString(), lexer::kEOF);
-  }
-
-  unicode::UniString return_string;
-  return_string += unicode::UniChar(reader->read());
-
-  int check_length = 0;
-  std::map<TokenType, int> check_map;
-
-  if (IsLexeme(return_string, &check_length)) {
-    check_map(lexer::lexeme::GetType(return_string), check_length);
-  }
-
-  
-}
old mode 100755 (executable)
new mode 100644 (file)
index 703b528..f5d3490
@@ -22,58 +22,40 @@ class UniString;
 
 namespace lexer {
 
-enum TokenType {
-  kEOF = -1,                            // ファイルの終端です。
-  kOpenParenthesis,                     // (を表します。
-  kCloseParenthesis,                    // )を表します。
-  kOpenBrackets,                        // [を表します。
-  kCloseBrackets,                       // ]を表します。
-  kDot,                                 // .を表します。
-  kVectorOpen,                          // #(を表します。
-  kByteVectorOpen,                      // #vu8(を表します。
-  kQuote,                               // '
-  kQuasiquote,                          // `
-  kUnquote,                             // ,
-  kUnquoteSplicing,                     // ,@
-  kSyntax,                              // #'
-  kQuasisyntax,                         // #`
-  kUnsyntax,                            // #,
-  kUnsyntaxSplicing,                    // #,@
-  kOpenNestedComment,                   // #|
-  kCloseNestedComment,                  // |#
-  kSemicolon,                           // ;
-  kExclamationMark,                     // !
-  kDoller,                              // $
-  kPercentage,                          // %
-  kAmp,                                 // &
-  kMultiply,                            // *
-  kSlash,                               // /
-  kColon,                               // :
-  kLessThan,                            // <
-  kEqual,                               // =
-  kGreaterThan,                         // >
-  kQuestion,                            // ?
-  kCap,                                 // ^
-  kUnderscore,                          // _
-  kTilda,                               // ~
-  kDigit,                               // 0-9
-  kLetter,                              // a-zA-Z
-};
+class Token;
+class IPartOfLexer;
+
+namespace detail {
+
+// 渡されたLexerを実行し、結果を指定されたtokenに設定するための
+// 関数オブジェクトです。
+struct GetToken {
+public:
+  GetToken(reader::EncodingReader* reader,
+           akebono::smart_ptr<lexer::Token>& token)
+      : reader_(reader), token_(token) {}
 
-struct Token {
-  // lexerで実行した結果の字句を返却するためのトークンクラスです。
-  // stringに読出した文字列と、TokenTypeを保持します。
-  Token(const unicode::UniString& string_, TokenType type_);
-  virtual ~Token() {}
+  template <typename T> bool operator()(T& lexer) {
+    akebono::smart_ptr<lexer::Token> result(lexer->Lex(reader_));
+    if (result.is_null()) {
+      return false;
+    }
+    token_ = result;
+    return true;
+  }
 
-  // 読出した文字列です。smart_ptrで保持されています。
-  akebono::smart_ptr<unicode::UniString> string;
+ private:
 
-  // 読出されたトークンのタイプです。
-  TokenType type;
+  // Lexerからの読出対象となるreaderです。
+  reader::EncodingReader* reader_;
+
+  // Lexerの結果を格納するためのTokenです。operator()がtrueを返却する場合、
+  // 設定されていた内部データに対する参照カウントは減らされます。
+  akebono::smart_ptr<lexer::Token>& token_;
 };
+} // end of namespace detail
 
-class RestrictiveLexer {
+class SchemeLexer {
   // Scheme構文のうち、指定された条件に該当するような構文に該当する文字列
   // が読出されているかどうかをチェックする機能のみを切り出した
   // 限定Lexerです。
@@ -81,40 +63,29 @@ class RestrictiveLexer {
   // を返します。
   // Lexに渡す関数は、特定のspecに対してのみ読み出しを行います。
  public:
-  RestrictiveLexer();
-  virtual ~RestrictiveLexer() {}
+
+  // 内部で利用するLexer群の初期化を行います。
+  SchemeLexer();
+  virtual ~SchemeLexer() {}
 
   // 渡されたEncodingReaderから、字句構文を解析します。
   // EncodingReaderの末尾に到達した場合、TokenType::kEOFが保持されている
   // Tokenが返されます。
-  Token* Lex(reader::EncodingReader* reader);
-};
+  akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
 
-namespace digit {
-// 渡された文字列が、Digitに該当するかどうかを返します。
-// ただしチェックするのは文字列の先頭のみとなります。
-bool IsDigit(const unicode::UniString& str, int* length);
-TokenType GetType(const unicode::UniString& str);
-}
+ private:
 
-namespace lexeme {
-// 渡された文字列が、<lexeme>の終端記号に該当するかどうかを返します。
-bool IsLexeme(const unicode::UniString& str, int* length);
-TokenType GetType(const unicode::UniString& str);
-}
+  // 渡されたreaderから、連続するInterlexeme spaceの読み飛ばしを行います。
+  // この読み飛ばし時、特殊形式のコメント、またはdatum commentが発見された
+  // 場合、そのトークンが返却されます。
+  akebono::smart_ptr<lexer::Token> SkipInterLexemeSpace(reader::EncodingReader* reader);
 
-namespace letter {
-// 渡された文字列の先頭が、letterに該当するかどうかを返します。
-// 文字列の先頭以外はチェックは行いません。
-bool IsLetter(const unicode::UniString& str, int* length);
-TokenType GetType(const unicode::UniString& str);
-}
+ private:
+
+  // 内部で利用される、IPartOfLexerから派生したLexer群です。
+  std::vector<akebono::smart_ptr<lexer::IPartOfLexer> > inner_lexers_;
+};
 
-namespace special_initial {
-// 渡された文字列の先頭が、special_initialに該当するかどうかを返します。
-bool IsSpecialInitial(const unicode::UniString& str, int* length);
-TokenType GetType(const unicode::UniString& str);
-}
 }
 }
 
old mode 100755 (executable)
new mode 100644 (file)
index 210b3ff..1d06dff
@@ -1,10 +1,11 @@
 #include <utility>
+#include "lib/smart_ptr.h"
 #include "src/exception_macro.h"
 #include "src/lexer/string_lexer.h"
 #include "src/lexer/term_lexer.h"
 #include "src/lexer/term_checker.h"
 #include "src/lexer/inline_hex_escape_lexer.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/encoding_reader.h"
 #include "src/unicode.h"
 
@@ -122,10 +123,11 @@ void lexer::EscapeLexer::ReadIntralines(reader::EncodingReader* reader) {
 // また、\から行末まで空白文字のみが続き、次の行の最初の文字までが、改行か
 // 空白のみである場合、その間の空白及び改行は無視され、文字列は継続している
 // とみなされます。
-lexer::Lexeme* lexer::StringLexer::Lex(reader::EncodingReader* reader) {
+akebono::smart_ptr<lexer::Token> lexer::StringLexer::Lex(
+    reader::EncodingReader* reader) {
   lexer::TermLexer<term::StringDoubleQuote> string_delimiter;
   if (!string_delimiter.CheckToken(reader)) {
-    return NULL;
+    return akebono::smart_ptr<lexer::Token>();
   }
   reader->Read(string_delimiter.previous_read_size());
 
@@ -155,5 +157,6 @@ lexer::Lexeme* lexer::StringLexer::Lex(reader::EncodingReader* reader) {
                      unicode::Convert("not found end of string."));
   }
 
-  return new lexer::Lexeme(str, lexer::Lexeme::kString);
+  return akebono::smart_ptr<lexer::Token>(
+      new lexer::Token(str, lexer::Token::kString));
 }
old mode 100755 (executable)
new mode 100644 (file)
index fcc4b45..d16b1da
@@ -19,7 +19,7 @@ class EncodingReader;
 }
 
 namespace lexer {
-class Lexeme;
+class Token;
 
 
 // エスケープ文字を判定し、各固定値を返却するためのfunctorです。
@@ -112,9 +112,9 @@ class StringLexer : public IPartOfLexer {
   virtual ~StringLexer() {}
 
   // 読出しストリームへのポインタを受け取って、結果として生成した
-  // Lexemeのポインタを返します。
+  // Tokenのポインタを返します。
   // 文字列の字句では無い場合、NULLが返却されます。
-  virtual Lexeme* Lex(reader::EncodingReader* reader);
+  virtual akebono::smart_ptr<lexer::Token> Lex(reader::EncodingReader* reader);
 };
 
 class StringLexerFactory : public ILexerCreator {
old mode 100755 (executable)
new mode 100644 (file)
index 19f3e7f..89391dc
@@ -314,3 +314,162 @@ bool term::NestedCommentClose::operator()(reader::IReader* reader,
   }
   return false;
 }
+
+// 宣言のコメントを参照してください。
+bool term::OpenParenthesis::operator()(reader::IReader* reader,
+                                       unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == '(') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::CloseParenthesis::operator()(reader::IReader* reader,
+                                       unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == ')') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::OpenBracket::operator()(reader::IReader* reader,
+                                   unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == '[') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::CloseBracket::operator()(reader::IReader* reader,
+                                    unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == ']') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Dot::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == '.') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+
+// 宣言のコメントを参照してください。
+bool term::OpenVector::operator()(reader::IReader* reader,
+                                  unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::Convert("#(")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::OpenByteVector::operator()(reader::IReader* reader,
+                                      unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::UniString("#vu8(")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Quote::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == '\'') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Quasiquote::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == '`') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Unquote::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniChar ch(reader->Peek());
+  if (ch.rawcode() == ',') {
+    *size = 1;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::UnquoteSplicing::operator()(reader::IReader* reader,
+                                       unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::Convert(",@")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Syntax::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::Convert("#'")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Quasisyntax::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::Convert("#`")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::Unsyntax::operator()(reader::IReader* reader, unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::Convert("#,")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
+
+// 宣言のコメントを参照してください。
+bool term::UnsyntaxSplicing::operator()(reader::IReader* reader,
+                                        unsigned int* size) {
+  unicode::UniString str(unicode::Convert(reader->Peek(kReadSize)));
+  if (str == unicode::Convert("#,@")) {
+    *size = kReadSize;
+    return true;
+  }
+  return false;
+}
index 4fe209e..a970aec 100644 (file)
@@ -361,6 +361,95 @@ struct NestedCommentClose {
   // trueを返した場合、sizeにはトークンの文字数が返却されます。
   bool operator()(reader::IReader* reader, unsigned int* size);
 };
+
+//-------------------------------------------------
+// <lexeme>中の各終端記号を定義します。それぞれ、関数オブジェクトとして
+// 利用します。
+//-------------------------------------------------
+
+// readerの先頭が ( に一致するかどうかをチェックします。
+struct OpenParenthesis {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が ) に一致するかどうかをチェックします。
+struct CloseParenthesis {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が [ に一致するかどうかをチェックします。
+struct OpenBracket {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が ] に一致するかどうかをチェックします。
+struct CloseBracket {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が . に一致するかどうかをチェックします。
+struct Dot {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が #( に一致するかどうかをチェックします。
+struct OpenVector {
+  // readerから読出すサイズです。
+  static const int kReadSize = 2;
+
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が #vu8( に一致するかどうかをチェックします。
+struct OpenByteVector {
+  static const int kReadSize = 5;
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が ' に一致するかどうかをチェックします。
+struct Quote {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が ` に一致するかどうかをチェックします。
+struct Quasiquote {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が , に一致するかどうかをチェックします。
+struct Unquote {
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が ,@ に一致するかどうかをチェックします。
+struct UnquoteSplicing {
+  static const int kReadSize = 2;
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が #' に一致するかどうかをチェックします。
+struct Syntax {
+  static const int kReadSize = 2;
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が #` に一致するかどうかをチェックします。
+struct Quasisyntax {
+  static const int kReadSize = 2;
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が #, に一致するかどうかをチェックします。
+struct Unsyntax {
+  static const int kReadSize = 2;
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
+
+// readerの先頭が #,@ に一致するかどうかをチェックします。
+struct UnsyntaxSplicing {
+  static const int kReadSize = 3;
+  bool operator()(reader::IReader* reader, unsigned int* size);
+};
 }
 }
 }
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
similarity index 50%
rename from src/lexeme.cpp
rename to src/lexer/token.cpp
index 10519bc..5b2a3ff
@@ -1,20 +1,21 @@
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 #include "src/unicode.h"
 
 namespace lexer = utakata::lexer;
 namespace unicode = utakata::unicode;
 
-lexer::Lexeme::Lexeme(const unicode::UniString& lexeme_str,
-                      const lexer::Lexeme::LexemeType type)
+
+lexer::Token::Token(const unicode::UniString& lexeme_str,
+                    const lexer::Token::TokenType type)
     : string_(new unicode::UniString(lexeme_str)),
       type_(type) {}
 
-lexer::Lexeme::Lexeme(const lexer::Lexeme& rh)
+lexer::Token::Token(const lexer::Token& rh)
     : string_(rh.string_),
       type_(rh.type_) {}
 
-lexer::Lexeme& lexer::Lexeme::operator=(const lexer::Lexeme& rh) {
-  lexer::Lexeme tmp(rh);
+lexer::Token& lexer::Token::operator=(const lexer::Token& rh) {
+  lexer::Token tmp(rh);
   string_ = tmp.string_;
   type_ = tmp.type_;
   return *this;
old mode 100755 (executable)
new mode 100644 (file)
similarity index 68%
rename from src/lexeme.h
rename to src/lexer/token.h
index fdee6e3..916191c
@@ -1,9 +1,11 @@
-// lexerによって作成されたlexemeを格納するためのインターフェースです。
-// 実体として存在し、内部では解釈された文字列と、lexemeのタイプのみが
+// lexerによって作成された各トークンを格納するためのインターフェースです。
+// 実体として存在し、内部では解釈された文字列と、tokenのタイプのみが
 // 格納されています。
 // 格納されたlexemeは、評価された時に改めて型にあった値に変更されます。
-#ifndef _DEVELOP_UTAKATA_SRC_LEXEME_H_
-#define _DEVELOP_UTAKATA_SRC_LEXEME_H_
+#ifndef _UTAKATA_SRC_LEXER_TOKEN_H_
+#define _UTAKATA_SRC_LEXER_TOKEN_H_
+
+
 
 #include "lib/smart_ptr.h"
 
@@ -15,16 +17,18 @@ class UniString;
 
 namespace lexer {
 
-class Lexeme {
+class Token {
   // 各非終端記号を表すためのクラスです。このクラスは、各Lexerによって
   // 作成され、一度作成された後は変更されることはありません。
   // 実際にはこのクラスより、それぞれの値に評価されます。
  public:
 
-  enum LexemeType {
+  enum TokenType {
     kEOS  = -1,
     kOpenParenthesis,
     kCloseParenthesis,
+    kOpenBracket,
+    kCloseBracket,
     kCharactor,
     kString,
     kBoolean,
@@ -32,30 +36,30 @@ class Lexeme {
     kByteVector,
     kNumber,
     kIdentifier,
-    kQuote,
-    kBackquote,
-    kQuasisyntax,
-    kSyntax,
     kDot,
+    kQuote,
     kQuasiquote,
-    kUnsyntax,
-    kUnsyntaxSplicing,
     kUnquote,
     kUnquoteSplicing,
+    kSyntax,
+    kQuasisyntax,
+    kUnsyntax,
+    kUnsyntaxSplicing,
     kDatumComment,
     kSpecialComment,
+    kComment,
     kUnToken,
   };
 
-  Lexeme() : string_(), type_(kUnToken) {}
-  Lexeme(const unicode::UniString& lexeme_str, const LexemeType type);
-  Lexeme(const Lexeme& other);
-  virtual ~Lexeme() {}
+  Token() : string_(), type_(kUnToken) {}
+  Token(const unicode::UniString& lexeme_str, const TokenType type);
+  Token(const Token& other);
+  virtual ~Token() {}
 
-  Lexeme& operator=(const Lexeme& rh);
+  Token& operator=(const Token& rh);
 
   // 各非終端記号などの型を表すenum値を返します。
-  const LexemeType type() const {return type_;}
+  const TokenType type() const {return type_;}
 
   // それぞれの型を表すデータです。型によって内容は異なります。
   const unicode::UniString& string() const {return *string_;}
@@ -65,9 +69,9 @@ class Lexeme {
   akebono::smart_ptr<unicode::UniString> string_;
 
   // lexemeの型を表すEnum値です。
-  LexemeType type_;
+  TokenType type_;
 };
 }
 }
 
-#endif /* _DEVELOP_UTAKATA_SRC_LEXEME_H_ */
+#endif /* _UTAKATA_SRC_LEXER_TOKEN_H_ */
similarity index 100%
rename from refactor_target/parser.h
rename to src/parser/parser.h
diff --git a/src/parser/syntax_tree.h b/src/parser/syntax_tree.h
new file mode 100755 (executable)
index 0000000..a332c2b
--- /dev/null
@@ -0,0 +1,109 @@
+// syntax_tree.h  -  declared `SyntaxTree` that it used by Parser
+// Parserクラスより利用される、内部の構文木を構築します。
+// 内部構文木は、構文データのみで表現される、構文データを表現するための
+// クラスとなります。
+// 内部では、lexer::Tokenより解析されたObjectクラスの派生クラスをそれぞれ
+// 保持します。内部的には、すべてobject::Consによって連接されたリストとして
+// 表現されます。
+#ifndef _UTAKATA_SRC_PARSER_SYNTAX_TREE_H_
+#define _UTAKATA_SRC_PARSER_SYNTAX_TREE_H_
+
+#include "lib/smart_ptr.h"
+#include <utility>              // std::pair
+#include <vector>
+
+namespace utakata {
+namespace unicode {
+class UniString;
+};
+
+namespace syntax {
+
+class DatumID;
+
+// データ構文を表現する、Lexemeから構築された構文木を表現します。
+// 内部では、Lexemeより作成された各プリミティブオブジェクトを保持し、
+// 完全なデータ構文木を作成します。
+// このデータ構文木は任意の数のdatumを含むことができますが、全体を構築
+// する際、表面上は一つだけcompound datumを含んでいるパターンが想定されます。
+class SyntaxTree {
+  // 実装でのみ定義される。
+  struct TreeNode;
+
+ public:
+
+  class iterator {
+   public:
+    // ツリーを巡回し、そのノードの literal を取得することを可能とする。
+    iterator ();
+    iterator (const iterator& s);
+
+    ~iterator () {}
+
+    iterator& operator=(const iterator& rh);
+    iterator& operator++ ();
+    node_pair& operator*();
+    node_pair* operator->();
+
+    // 一致するかどうかを返す
+    bool operator==(const iterator& rh);
+    bool operator!=(const iterator& rh) {
+      return ! (*this == rh);
+    }
+
+    // 現在位置を表すiterator
+    std::vector<smart_ptr<TreeNode> >::iterator current_;
+
+   private:
+
+    void swap (const iterator& s);
+
+  };
+ public:
+
+  Tree ();
+  virtual ~Tree () {}
+
+  // 現在の Tree の先頭=root node と、 end = 次に指す場所が存在しない
+  // node を返す。
+  iterator begin ();
+  iterator end ();
+
+  // push_backによって追加を行う。
+  void push_back (node_pair datum);
+  void push_back (iterator b, iterator e, node_pair datum);
+
+  // itが指すnodeの内部listの先頭を返す。
+  iterator in_compound_begin(iterator it);
+  iterator in_compound_end(iterator it);
+
+  size_t size() const {return node_.size();}
+
+ private:
+
+  std::vector<smart_ptr<TreeNode> > node_;
+
+};
+
+// 渡した iterator が list datum であるかどうかを返す。
+bool isCompoundDatum (Tree::iterator node);
+
+// 渡した node が literal であるかどうかを返す。
+bool isLiteral (Tree::iterator node);
+
+// 各 datum を表す std::pair を作成するためのヘルパ関数。
+std::pair<DatumID, smart_ptr<literal::Literal> > makeCompoundDatum (
+    DatumID id);
+
+std::pair<DatumID, smart_ptr<literal::Literal> > makeNilList ();
+std::pair<DatumID, smart_ptr<literal::Literal> > makeLexemeDatum (smart_ptr<literal::Literal> l,
+                                                                  DatumID id);
+std::pair<DatumID, smart_ptr<literal::Literal> > makeAbbreviation (smart_ptr<literal::Literal> l);
+
+// 渡したtreeの内容を文字列に変換する。
+//        smart_ptr<unicode::UniString> treeToValue(Tree& t);
+};
+
+};
+
+#endif /* _UTAKATA_SRC_PARSER_SYNTAX_TREE_H_ */
diff --git a/test/binary_tree_test.cpp b/test/binary_tree_test.cpp
new file mode 100755 (executable)
index 0000000..9ad41db
--- /dev/null
@@ -0,0 +1,127 @@
+#include <test/gtest/gtest.h>
+#include <string>
+#include "src/encoding_reader.h"
+#include "src/string_reader.h"
+#include "src/unicode.h"
+#include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
+#include "lib/binary_tree.h"
+#include "src/utf8_transcoder.h"
+#include "src/lexer/token.h"
+
+namespace unicode = utakata::unicode;
+namespace reader = utakata::reader;
+namespace transcoder = utakata::transcoder;
+
+TEST(BinaryTreeTest, PreorderUse) {
+  akebono::binary_tree<std::string> string_tree;
+  akebono::binary_tree<std::string>::iterator top =
+      string_tree.begin(), left, right;
+
+  // Return begin() is top of `string_tree`. It is root.
+  top = string_tree.insert(top, "root");
+  left = string_tree.set_left(top, "child1");
+  right = string_tree.set_right(top, "child2");
+
+  string_tree.set_right(left, "left child1");
+  string_tree.set_left(right, "right child1");
+  string_tree.set_right(right, "right child2");
+
+  akebono::binary_tree<std::string>::inorder_iterator top =
+      string_tree.preorder_begin();
+
+  EXPECT_EQ(*top, "root"); ++top;
+  EXPECT_EQ(*top, "child1"); top++;
+  EXPECT_EQ(*top, "left child1"); ++top;
+  EXPECT_EQ(*top, "child2"); ++top;
+  EXPECT_EQ(*top, "right child1"); ++top;
+  EXPECT_EQ(*top, "right child2"); ++top;
+  EXPECT_EQ(top, string_tree.preorder_end());
+}
+
+TEST(BinaryTreeTest, PostorderUse) {
+  akebono::binary_tree<std::string> string_tree;
+  akebono::binary_tree<std::string>::iterator top =
+      string_tree.begin(), left, right;
+
+  // Return begin() is top of `string_tree`. It is root.
+  top = string_tree.insert(top, "root");
+  left = string_tree.set_left(top, "child1");
+  right = string_tree.set_right(top, "child2");
+
+  string_tree.set_right(left, "left child1");
+  string_tree.set_left(right, "right child1");
+  string_tree.set_right(right, "right child2");
+
+  akebono::binary_tree<std::string>::inorder_iterator top =
+      string_tree.postorder_begin();
+
+  EXPECT_EQ(*top, "left child1"); top++;
+  EXPECT_EQ(*top, "child1"); ++top;
+  EXPECT_EQ(*top, "right child1"); ++top;
+  EXPECT_EQ(*top, "right child2"); ++top;
+  EXPECT_EQ(*top, "child2"); ++top;
+  EXPECT_EQ(*top, "root"); ++top;
+  EXPECT_EQ(top, string_tree.preorder_end());
+}
+
+TEST(BinaryTreeTest, InorderUse) {
+  akebono::binary_tree<std::string> string_tree;
+  akebono::binary_tree<std::string>::iterator top =
+      string_tree.begin(), left, right;
+
+  // Return begin() is top of `string_tree`. It is root.
+  top = string_tree.insert(top, "root");
+  left = string_tree.set_left(top, "child1");
+  right = string_tree.set_right(top, "child2");
+
+  string_tree.set_right(left, "left child1");
+  string_tree.set_left(right, "right child1");
+  string_tree.set_right(right, "right child2");
+
+  akebono::binary_tree<std::string>::inorder_iterator top =
+      string_tree.inorder_begin();
+
+  EXPECT_EQ(*top, "left child1"); top++;
+  EXPECT_EQ(*top, "child1"); ++top;
+  EXPECT_EQ(*top, "root"); ++top;
+  EXPECT_EQ(*top, "right child1"); ++top;
+  EXPECT_EQ(*top, "child2"); ++top;
+  EXPECT_EQ(*top, "right child2"); ++top;
+  EXPECT_EQ(top, string_tree.inorder_end());
+}
+
+TEST(BinaryTreeTest, SExpLikeUse) {
+  akebono::binary_tree<std::string> string_tree;
+  akebono::binary_tree<std::string>::iterator top =
+      string_tree.begin(), left, right;
+
+  // Return begin() is top of `string_tree`. It is root.
+  // create tree from SExp as "((child1 3) child2 (hoge) (huga))"
+  top = string_tree.insert(top, "root");
+  left = string_tree.set_left(top, "child1");
+  left = string_tree.set_right(left, "3");
+  right = string_tree.set_right(top, "child2");
+  left = string_tree.set_right(right, "hoge_cons");
+  left = string_tree.set_left(left, "hoge");
+  right = string_tree.set_right(right, "huga_cons");
+  right = string_tree.set_left(right, "huga");
+
+  akebono::binary_tree<std::string>::preorder_iterator top =
+      string_tree.inorder_begin();
+
+  EXPECT_EQ(*top, "root"); top++;       // it's not uses
+  EXPECT_EQ(*top, "child1"); ++top;
+  EXPECT_EQ(*top, "3"); ++top;
+  EXPECT_EQ(*top, "child2"); ++top;
+  EXPECT_EQ(*top, "hoge_cons"); ++top;  // it's not uses
+  EXPECT_EQ(*top, "hoge"); ++top;
+  EXPECT_EQ(*top, "huga_cons"); ++top;  // it's not uses
+  EXPECT_EQ(*top, "huga"); ++top;
+  EXPECT_EQ(top, string_tree.inorder_end());
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
index 37d768a..dd17553 100755 (executable)
@@ -5,8 +5,9 @@
 #include "src/string_reader.h"
 #include "src/unicode.h"
 #include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
 #include "src/utf8_transcoder.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 
 namespace textarrayformat = utility::textarrayformat;
 namespace lexer = utakata::lexer;
@@ -31,38 +32,38 @@ TEST_F(BooleanLexerTest, BooleanCheck) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::BooleanLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_TRUE(l->string() == unicode::Convert("#t"));
   EXPECT_EQ(l->string().GetSize(), 2);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kBoolean);
+  EXPECT_EQ(l->type(), lexer::Token::kBoolean);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_TRUE(l->string() == unicode::Convert("#T"));
   EXPECT_EQ(l->string().GetSize(), 2);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kBoolean);
+  EXPECT_EQ(l->type(), lexer::Token::kBoolean);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_TRUE(l->string() == unicode::Convert("#f"));
   EXPECT_EQ(l->string().GetSize(), 2);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kBoolean);
+  EXPECT_EQ(l->type(), lexer::Token::kBoolean);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_TRUE(l->string() == unicode::Convert("#F"));
   EXPECT_EQ(l->string().GetSize(), 2);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kBoolean);
+  EXPECT_EQ(l->type(), lexer::Token::kBoolean);
 
   reader.Read();
   EXPECT_THROW(lexer.Lex(&reader), lexer::LexException);
 
   reader.Read(2);
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() ==  NULL);
 }
 
index da3aef6..cba701a 100755 (executable)
@@ -5,8 +5,9 @@
 #include "src/string_reader.h"
 #include "src/unicode.h"
 #include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
 #include "src/utf8_transcoder.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 
 namespace textarrayformat = utility::textarrayformat;
 namespace lexer = utakata::lexer;
@@ -40,25 +41,25 @@ TEST_F(CharactorLexerTest, SingleCharactorLex) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::CharactorLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_EQ(l->string().At(0).rawcode(), 'a');
   EXPECT_EQ(l->string().GetSize(), 1);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kCharactor);
+  EXPECT_EQ(l->type(), lexer::Token::kCharactor);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_EQ(l->string().At(0).rawcode(), 'z');
   EXPECT_EQ(l->string().GetSize(), 1);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kCharactor);
+  EXPECT_EQ(l->type(), lexer::Token::kCharactor);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_EQ(l->string().At(0).rawcode(), 'x');
   EXPECT_EQ(l->string().GetSize(), 1);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kCharactor);
+  EXPECT_EQ(l->type(), lexer::Token::kCharactor);
 
   reader.Read(2);
   EXPECT_THROW(lexer.Lex(&reader), lexer::LexException);
@@ -71,31 +72,31 @@ TEST_F(CharactorLexerTest, HexCharactorTest) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::CharactorLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
 
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_EQ(l->string().At(0).rawcode(), 0x01);
   EXPECT_EQ(l->string().GetSize(), 1);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kCharactor);
+  EXPECT_EQ(l->type(), lexer::Token::kCharactor);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_EQ(l->string().At(0).rawcode(), 0x7f8f);
   EXPECT_EQ(l->string().GetSize(), 1);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kCharactor);
+  EXPECT_EQ(l->type(), lexer::Token::kCharactor);
 }
 
 TEST_F(CharactorLexerTest, NameLexingNul) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   {
     reader::StringReader sr(textarray.GetBlockAt(2));
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x0);
     EXPECT_EQ(l->string().GetSize(), 1);
@@ -119,13 +120,13 @@ TEST_F(CharactorLexerTest, NameLexingNul) {
 
 TEST_F(CharactorLexerTest, NameLexingAlarm) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   {
     reader::StringReader sr(textarray.GetBlockAt(3));
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x07);
     EXPECT_EQ(l->string().GetSize(), 1);
@@ -149,13 +150,13 @@ TEST_F(CharactorLexerTest, NameLexingAlarm) {
 
 TEST_F(CharactorLexerTest, NameLexingBackspace) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   {
     reader::StringReader sr(textarray.GetBlockAt(4));
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x08);
     EXPECT_EQ(l->string().GetSize(), 1);
@@ -179,19 +180,19 @@ TEST_F(CharactorLexerTest, NameLexingBackspace) {
 
 TEST_F(CharactorLexerTest, NameLexingTabAndLinefeed) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   {
     reader::StringReader sr(textarray.GetBlockAt(5));
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x09);
     EXPECT_EQ(l->string().GetSize(), 1);
 
     reader.Read();
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x0a);
     EXPECT_EQ(l->string().GetSize(), 1);
@@ -215,25 +216,25 @@ TEST_F(CharactorLexerTest, NameLexingTabAndLinefeed) {
 
 TEST_F(CharactorLexerTest, NameLexing) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   {
     reader::StringReader sr(textarray.GetBlockAt(6));
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x0A);
     EXPECT_EQ(l->string().GetSize(), 1);
 
     reader.Read();
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x0B);
     EXPECT_EQ(l->string().GetSize(), 1);
 
     reader.Read();
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x0C);
     EXPECT_EQ(l->string().GetSize(), 1);
@@ -244,19 +245,19 @@ TEST_F(CharactorLexerTest, NameLexing) {
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x0D);
     EXPECT_EQ(l->string().GetSize(), 1);
 
     reader.Read();
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x1B);
     EXPECT_EQ(l->string().GetSize(), 1);
 
     reader.Read();
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x20);
     EXPECT_EQ(l->string().GetSize(), 1);
@@ -265,13 +266,13 @@ TEST_F(CharactorLexerTest, NameLexing) {
 
 TEST_F(CharactorLexerTest, NameLexingDelete) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   {
     reader::StringReader sr(textarray.GetBlockAt(8));
     reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
     lexer::CharactorLexer lexer;
 
-    l.reset(lexer.Lex(&reader));
+    l = lexer.Lex(&reader);
     EXPECT_TRUE(l.get() != NULL);
     EXPECT_EQ(l->string().At(0).rawcode(), 0x7f);
     EXPECT_EQ(l->string().GetSize(), 1);
index 512faa7..ca16b35 100755 (executable)
@@ -5,8 +5,9 @@
 #include "src/string_reader.h"
 #include "src/unicode.h"
 #include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
 #include "src/utf8_transcoder.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 
 namespace textarrayformat = utility::textarrayformat;
 namespace lexer = utakata::lexer;
@@ -34,12 +35,13 @@ TEST_F(CommentLexerTest, OnelineComment) {
   reader::StringReader sr(textarray.GetBlockAt(0));
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
+  akebono::smart_ptr<lexer::Token> l;
   lexer::CommentLexer lexer;
-  EXPECT_FALSE(lexer.Lex(&reader));
+  EXPECT_FALSE(lexer.Lex(&reader, l));
   reader.Read(7);
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() == NULL);
+  EXPECT_TRUE(lexer.Lex(&reader, l));
+  EXPECT_TRUE(l.is_null());
   unicode::UniString st(unicode::Convert(reader.Read(4)));
   EXPECT_TRUE(st == unicode::UniString("huga"));
 }
@@ -51,43 +53,44 @@ TEST_F(CommentLexerTest, SpecialComment) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::CommentLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
+  akebono::smart_ptr<lexer::Token> l;
+  EXPECT_TRUE(lexer.Lex(&reader, l));
 
-  EXPECT_TRUE(l.get() != NULL);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kSpecialComment);
+  EXPECT_EQ(l->type(), lexer::Token::kSpecialComment);
   reader.Read();
   EXPECT_TRUE(reader.IsEof());
 }
 
 TEST_F(CommentLexerTest, BlockCommentNoNested) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+
   reader::StringReader sr(textarray.GetBlockAt(2));
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::CommentLexer lexer;
-  l.reset(lexer.Lex(&reader));
+  akebono::smart_ptr<lexer::Token> l;
+  EXPECT_TRUE(lexer.Lex(&reader, l));
 
-  EXPECT_TRUE(l.get() == NULL);
   unicode::UniString tmp(unicode::Convert(reader.Read(2)));
   EXPECT_TRUE(tmp == unicode::Convert("ss"));
 }
 
 TEST_F(CommentLexerTest, NestedBlockComment) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+
   reader::StringReader sr(textarray.GetBlockAt(3));
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::CommentLexer lexer;
-  l.reset(lexer.Lex(&reader));
 
-  EXPECT_TRUE(lexer.Lex(&reader) == NULL);
+  akebono::smart_ptr<lexer::Token> l;
+  EXPECT_TRUE(lexer.Lex(&reader, l));
+
   unicode::UniString tmp(unicode::Convert(reader.Read(3)));
   EXPECT_TRUE(tmp == unicode::Convert("123"));
 }
 
 TEST_F(CommentLexerTest, DatumComment) {
   textarrayformat::TextArrayReader textarray(*gen);
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   reader::StringReader sr(textarray.GetBlockAt(4));
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::CommentLexer lexer;
@@ -97,8 +100,9 @@ TEST_F(CommentLexerTest, DatumComment) {
   // 関係上、字句解析ではなく構文解析レベルでのコメントが必要となるため、
   // その判別が必要であるためです。
   // datum commentは、その性質上、幾重にもネストする可能性があります。
-  l.reset(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  EXPECT_TRUE(lexer.Lex(&reader, l));
+
+  EXPECT_EQ(l->type(), lexer::Token::kDatumComment);
   unicode::UniString tmp(unicode::Convert(reader.Read(4)));
   EXPECT_TRUE(tmp == unicode::Convert("data"));
 }
diff --git a/test/datum_test.cpp b/test/datum_test.cpp
new file mode 100755 (executable)
index 0000000..7833589
--- /dev/null
@@ -0,0 +1,52 @@
+#include <iostream>
+#include <test/gtest/gtest.h>
+#include "lib/smart_ptr.h"
+#include "src/datum.h"
+#include "src/object.h"
+#include "src/unicode.h"
+
+namespace data = utakata::data;
+namespace interpreter = utakata::interpreter;
+namespace unicode = utakata::unicode;
+namespace datum = utakata::datum;
+
+using namespace akebono;
+
+class TestObject : public interpreter::IObject {
+ public:
+  virtual ~TestObject() {}
+
+  interpreter::IObject* Clone() const {
+    return NULL;
+  }
+
+  unicode::UniString* ToString() const {
+    return NULL;
+  }
+
+  interpreter::IObject* Eval(interpreter::Environment* env) {
+    return NULL;
+  }
+};
+
+TEST(DatumTest, LexemeDatumTest) {
+  smart_ptr<datum::IDatumBase> symbol(new datum::Symbol(
+      unicode::Convert("symbol")));
+
+  smart_ptr<datum::IDatumBase> str(new datum::String(
+      unicode::Convert("\"string\"")));
+
+  smart_ptr<datum::IDatumBase> number(new datum::Number(
+      unicode::Convert("102")));
+
+  smart_ptr<datum::IDatumBase> boolean(new datum::Boolean(
+      unicode::Convert("#t")));
+  
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
+
index 3848067..dff6a59 100755 (executable)
@@ -6,7 +6,7 @@
 #include "src/unicode.h"
 #include "lib/scoped_ptr.h"
 #include "src/utf8_transcoder.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 
 namespace textarrayformat = utility::textarrayformat;
 namespace lexer = utakata::lexer;
@@ -37,25 +37,25 @@ TEST_F(IdentifierLexerTest, NormalIdentifer) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::IdentifierLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
   EXPECT_TRUE(l.get() != NULL);
   EXPECT_TRUE(l->string() == unicode::Convert("lambda"));
   EXPECT_EQ(l->string().GetSize(), 6);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kIdentifier);
+  EXPECT_EQ(l->type(), lexer::Token::kIdentifier);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("q"));
   EXPECT_EQ(l->string().GetSize(), 1);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kIdentifier);
+  EXPECT_EQ(l->type(), lexer::Token::kIdentifier);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("soup"));
   EXPECT_EQ(l->string().GetSize(), 4);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kIdentifier);
+  EXPECT_EQ(l->type(), lexer::Token::kIdentifier);
 }
 
 
@@ -66,18 +66,18 @@ TEST_F(IdentifierLexerTest, IgnoreCapital) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::IdentifierLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l = lexer.Lex(&reader);
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("<="));
   EXPECT_EQ(l->string().GetSize(), 2);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kIdentifier);
+  EXPECT_EQ(l->type(), lexer::Token::kIdentifier);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("a34kTMNs?"));
   EXPECT_EQ(l->string().GetSize(), 9);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kIdentifier);
+  EXPECT_EQ(l->type(), lexer::Token::kIdentifier);
 }
 
 TEST_F(IdentifierLexerTest, LongIdentifer) {
@@ -87,12 +87,12 @@ TEST_F(IdentifierLexerTest, LongIdentifer) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::IdentifierLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert(
       "the-word-recursion-has-maney-meanings"));
   EXPECT_EQ(l->string().GetSize(), 37);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kIdentifier);
+  EXPECT_EQ(l->type(), lexer::Token::kIdentifier);
 }
 
 TEST_F(IdentifierLexerTest, SpecialInitials) {
@@ -102,8 +102,8 @@ TEST_F(IdentifierLexerTest, SpecialInitials) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::IdentifierLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("!$%&*+-./:?@^_~"));
   EXPECT_EQ(l->string().GetSize(), 15);
 }
@@ -115,14 +115,14 @@ TEST_F(IdentifierLexerTest, InlineEscape) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::IdentifierLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("aiueo"));
   EXPECT_EQ(l->string().GetSize(), 5);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("abcd"));
   EXPECT_EQ(l->string().GetSize(), 4);
 }
@@ -134,23 +134,23 @@ TEST_F(IdentifierLexerTest, Errors) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::IdentifierLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l;
+  akebono::smart_ptr<lexer::Token> l;
   EXPECT_THROW(lexer.Lex(&reader), lexer::LexException);
 
   reader.Read(2);
-  EXPECT_THROW(l.reset(lexer.Lex(&reader)), lexer::LexException);
+  EXPECT_THROW(lexer.Lex(&reader), lexer::LexException);
 
   reader.Read(2);
-  EXPECT_NO_THROW(l.reset(lexer.Lex(&reader)));
+  EXPECT_NO_THROW(lexer.Lex(&reader));
 
   reader.Read();
-  EXPECT_NO_THROW(l.reset(lexer.Lex(&reader)));
-  EXPECT_TRUE(l.get() != NULL);
+  EXPECT_NO_THROW(l = lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("..."));
   EXPECT_EQ(l->string().GetSize(), 3);
 
   reader.Read();
-  EXPECT_THROW(l.reset(lexer.Lex(&reader)), lexer::LexException);
+  EXPECT_THROW(lexer.Lex(&reader), lexer::LexException);
 }
 
 int main(int argc, char** argv) {
diff --git a/test/lexeme_lexer_test.cpp b/test/lexeme_lexer_test.cpp
new file mode 100755 (executable)
index 0000000..377cd52
--- /dev/null
@@ -0,0 +1,128 @@
+#include <test/gtest/gtest.h>
+#include "lib/textarrayformat.h"
+#include "src/lexer/lexeme_lexer.h"
+#include "src/encoding_reader.h"
+#include "src/string_reader.h"
+#include "src/unicode.h"
+#include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
+#include "src/utf8_transcoder.h"
+#include "src/lexer/token.h"
+
+namespace textarrayformat = utility::textarrayformat;
+namespace lexer = utakata::lexer;
+namespace unicode = utakata::unicode;
+namespace reader = utakata::reader;
+namespace transcoder = utakata::transcoder;
+
+class LexemeLexerTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    gen.reset(new textarrayformat::TextArrayGenerator("========="));
+    gen->Punctuate("()[] .;");
+    gen->Punctuate("#() #vu8('`,,@");
+    gen->Punctuate("#'#`#,#,@");
+  }
+
+  akebono::scoped_ptr<textarrayformat::TextArrayGenerator> gen;
+};
+
+TEST_F(LexemeLexerTest, ParenAndBracket) {
+  textarrayformat::TextArrayReader textarray(*gen);
+
+  reader::StringReader sr(textarray.GetBlockAt(0));
+  reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
+  lexer::LexemeLexer lexer;
+
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
+  EXPECT_TRUE(l->string() == unicode::Convert("("));
+  EXPECT_EQ(l->string().GetSize(), 1);
+  EXPECT_EQ(l->type(), lexer::Token::kOpenParenthesis);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert(")"));
+  EXPECT_EQ(l->type(), lexer::Token::kCloseParenthesis);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("["));
+  EXPECT_EQ(l->type(), lexer::Token::kOpenBracket);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("]"));
+  EXPECT_EQ(l->type(), lexer::Token::kCloseBracket);
+
+  reader.Read();
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("."));
+  EXPECT_EQ(l->type(), lexer::Token::kDot);
+}
+
+TEST_F(LexemeLexerTest, Vectors) {
+  textarrayformat::TextArrayReader textarray(*gen);
+
+  reader::StringReader sr(textarray.GetBlockAt(1));
+  reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
+
+  lexer::LexemeLexer lexer;
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
+  EXPECT_TRUE(l->string() == unicode::Convert("#("));
+  EXPECT_EQ(l->string().GetSize(), 2);
+  EXPECT_EQ(l->type(), lexer::Token::kVector);
+
+  reader.Read(2);
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l.get() != NULL);
+  EXPECT_TRUE(l->string() == unicode::Convert("#vu8("));
+  EXPECT_EQ(l->string().GetSize(), 5);
+  EXPECT_EQ(l->type(), lexer::Token::kByteVector);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("'"));
+  EXPECT_EQ(l->type(), lexer::Token::kQuote);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("`"));
+  EXPECT_EQ(l->type(), lexer::Token::kQuasiquote);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert(","));
+  EXPECT_EQ(l->type(), lexer::Token::kUnquote);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert(",@"));
+  EXPECT_EQ(l->type(), lexer::Token::kUnquoteSplicing);
+}
+
+TEST_F(LexemeLexerTest, Unsyntaxes) {
+  textarrayformat::TextArrayReader textarray(*gen);
+
+  reader::StringReader sr(textarray.GetBlockAt(2));
+  reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
+  lexer::LexemeLexer lexer;
+
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(l.get() != NULL);
+  EXPECT_TRUE(l->string() == unicode::Convert("#'"));
+  EXPECT_EQ(l->string().GetSize(), 2);
+  EXPECT_EQ(l->type(), lexer::Token::kSyntax);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("#`"));
+  EXPECT_EQ(l->type(), lexer::Token::kQuasisyntax);
+
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("#,"));
+  EXPECT_EQ(l->type(), lexer::Token::kUnsyntax);
+
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(l->string() == unicode::Convert("#,@"));
+  EXPECT_EQ(l->type(), lexer::Token::kUnsyntaxSplicing);
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/lexer_test.cpp.bk b/test/lexer_test.cpp.bk
deleted file mode 100755 (executable)
index d2b0bbe..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <functional>
-
-#include "../simpletest.h"
-
-#include "../textarrayformat.h"
-#include "../lexeme_id.h"
-#include "../reader.h"
-#include "../utf8_transcoder.h"
-#include "../unicode.h"
-
-#include "../lexer.h"
-#include "../lexeme.h"
-
-using namespace std;
-using namespace utakata;
-
-bool lexer_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
-{
-    std::stringstream ss;
-    ss << "==========" << endl;
-    ss << "(hoge 12 \"hoge\" )" << endl;
-
-    textarrayformat::TextArrayReader reader(ss);
-    smart_ptr<istream> formats(new stringstream(reader.get()));
-    smart_ptr<utakata::reader::StreamReader> st(
-        new utakata::reader::StreamReader(formats,
-                                          smart_ptr<transcoder::ITranscoder>(
-                                              new transcoder::UTF8Transcoder())));
-    
-    utakata::lexer::Lexer lexer;
-
-    smart_ptr<lexeme::ILexeme> m(lexer.lex(st));
-    asserter->checkOnly((*m->toString())[0].getRawCode(), '(');
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::openParenthesis.toEnum(), "open paren");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::number.toEnum(), "number");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::string.toEnum(), "string");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-
-    // ここで終了しているはず。EOFの状態から実行されると、EOFのIDを持った
-    // lexemeが返される。
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::eos.toEnum(), "eos");
-    
-    return asserter->isOk();
-}
-
-bool lexer_test2(smart_ptr<simpletest::SimpleTestAsserter> asserter)
-{
-    std::stringstream ss;
-    ss << "==========" << endl;
-    ss << ",@(hoge 12 `(hoge) 'huga #f #t)" << endl;
-
-
-    textarrayformat::TextArrayReader reader(ss);
-    smart_ptr<istream> formats(new stringstream(reader.get()));
-    smart_ptr<utakata::reader::StreamReader> st(
-        new utakata::reader::StreamReader(formats,
-                                          smart_ptr<transcoder::ITranscoder>(
-                                              new transcoder::UTF8Transcoder())));
-    
-    utakata::lexer::Lexer lexer;
-
-    smart_ptr<lexeme::ILexeme> m(lexer.lex(st));
-    asserter->checkOnly((*m->toString())[0].getRawCode(), ',');
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::openParenthesis.toEnum(), "open paren");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::number.toEnum(), "number");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::backquote.toEnum(), "back quote");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::openParenthesis.toEnum(), "open paren2");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier2");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::quote.toEnum(), "quote");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier2");
-
-    // booleanの解析が行えるかどうか。
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::boolean.toEnum(), "boolean:false");
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::boolean.toEnum(), "boolean:true");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-
-    // ここで終了しているはず。EOFの状態から実行されると、EOFのIDを持った
-    // lexemeが返される。
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::eos.toEnum(), "eos");
-    
-    return asserter->isOk();
-}
-
-bool lexer_test3(smart_ptr<simpletest::SimpleTestAsserter> asserter)
-{
-    std::stringstream ss;
-    ss << "==========" << endl;
-    ss << "#'(hoge #,12 #`(hoge) 'huga) ; comment" << endl;
-    ss << "hoge #vu8(12 12) #(vector)" << endl;
-
-    textarrayformat::TextArrayReader reader(ss);
-    smart_ptr<istream> formats(new stringstream(reader.get()));
-    smart_ptr<utakata::reader::StreamReader> st(
-        new utakata::reader::StreamReader(formats,
-                                          smart_ptr<transcoder::ITranscoder>(
-                                              new transcoder::UTF8Transcoder())));
-    utakata::lexer::Lexer lexer;
-
-    smart_ptr<lexeme::ILexeme> m(lexer.lex(st));
-    asserter->checkOnly((*m->toString())[0].getRawCode(), '#', "syntax");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::openParenthesis.toEnum(), "open paren");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier");
-
-    m = lexer.lex(st);
-    asserter->checkOnly((*m->toString())[1].getRawCode(), ',', "unsyntax");
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::unsyntax.toEnum(), "unsyntax");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::number.toEnum(), "number");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::quasiSyntax.toEnum(), "quasi syntax");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::openParenthesis.toEnum(), "open paren2");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier2");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::quote.toEnum(), "quote");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier2");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "identifier3");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::byteVector.toEnum(), "byteVector");
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::number.toEnum(), "byteVector:number1");
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::number.toEnum(), "byteVector:number2");
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::vector.toEnum(), "vector");
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::identifier.toEnum(), "vector:identifier");
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::closeParenthesis.toEnum(), "close");
-    
-    // ここで終了しているはず。EOFの状態から実行されると、EOFのIDを持った
-    // lexemeが返される。
-    m = lexer.lex(st);
-    asserter->checkOnly(m->getID().toEnum(), lexeme::LexemeID::eos.toEnum(), "eos");
-    
-    return asserter->isOk();
-}
-
-
-int main(int argc, char *argv[])
-{
-    simpletest::SimpleTestSuite suite("main lexer test");
-    suite.addTester(sfcr::screate(lexer_test, suite.getAsserter()));
-    suite.addTester(sfcr::screate(lexer_test2, suite.getAsserter()));
-    suite.addTester(sfcr::screate(lexer_test3, suite.getAsserter()));
-    suite.run();
-    return 0;
-}
index 33a0524..f5bfb8e 100755 (executable)
@@ -5,8 +5,9 @@
 #include "src/string_reader.h"
 #include "src/unicode.h"
 #include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
 #include "src/utf8_transcoder.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 
 namespace textarrayformat = utility::textarrayformat;
 namespace lexer = utakata::lexer;
@@ -35,31 +36,31 @@ TEST_F(NumberLexerTest, DecimalLex) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::NumberLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l;
-  l.reset(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l;
+  l = lexer.Lex(&reader);
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("10"));
   EXPECT_EQ(l->string().GetSize(), 2);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kNumber);
+  EXPECT_EQ(l->type(), lexer::Token::kNumber);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("10.0"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("-10"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("-9.02"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("-9.1+0i"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("3/4"));
 }
 
@@ -70,22 +71,22 @@ TEST_F(NumberLexerTest, BinaryLex) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::NumberLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("#b010111"));
   EXPECT_EQ(l->string().GetSize(), 8);
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#b+1001"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#b-0001"));
 
   try {
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#b10/001"));
   } catch (utakata::exception::Exception& e) {
     std::cout << unicode::Convert(e.message()) << std::endl;
@@ -99,20 +100,20 @@ TEST_F(NumberLexerTest, OctetLex) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::NumberLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("#o0777"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#o+712"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#O-7346"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#o75/21"));
 }
 
@@ -123,20 +124,20 @@ TEST_F(NumberLexerTest, HexLex) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::NumberLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("#xFDa71"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#x+b92"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#X-C0A"));
 
   reader.Read();
-  l.reset(lexer.Lex(&reader));
+  l = lexer.Lex(&reader);
   EXPECT_TRUE(l->string() == unicode::Convert("#xaE/2f"));
 }
 
@@ -147,11 +148,11 @@ TEST_F(NumberLexerTest, Errors) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::NumberLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l;
-  EXPECT_NO_THROW(l.reset(lexer.Lex(&reader)));
+  akebono::smart_ptr<lexer::Token> l;
+  EXPECT_NO_THROW(lexer.Lex(&reader));
 
   reader.Read(6);
-  EXPECT_NO_THROW(l.reset(lexer.Lex(&reader)));
+  EXPECT_NO_THROW(lexer.Lex(&reader));
 }
 
 int main(int argc, char** argv) {
diff --git a/test/scheme_lexer_test.cpp b/test/scheme_lexer_test.cpp
new file mode 100755 (executable)
index 0000000..a68a297
--- /dev/null
@@ -0,0 +1,100 @@
+#include <test/gtest/gtest.h>
+#include "lib/textarrayformat.h"
+#include "src/lexer/scheme_lexer.h"
+#include "src/encoding_reader.h"
+#include "src/string_reader.h"
+#include "src/unicode.h"
+#include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
+#include "src/utf8_transcoder.h"
+#include "src/lexer/token.h"
+
+namespace textarrayformat = utility::textarrayformat;
+namespace lexer = utakata::lexer;
+namespace unicode = utakata::unicode;
+namespace reader = utakata::reader;
+namespace transcoder = utakata::transcoder;
+
+class SchemeLexerTest : public ::testing::Test {
+ protected:
+  virtual void SetUp() {
+    gen.reset(new textarrayformat::TextArrayGenerator("========="));
+    gen->Punctuate("#|\n \
+   The FACT procedure computes the factorial\n \
+ of a non-negative integer.\n \
+|#\n \
+(define fact\n \
+  (lambda (n)\n \
+    ;; base case\n \
+    (if (= n 0)\n \
+        #;(= n 1)\n \
+        1       ; identity of *\n \
+        (* n (fact (- n '1))))))");
+    gen->Punctuate("#() #vu8('`,,@");
+    gen->Punctuate("#'#`#,#,@");
+  }
+
+  akebono::scoped_ptr<textarrayformat::TextArrayGenerator> gen;
+};
+
+template <typename T>
+T& TestHelper(T& ptr, reader::EncodingReader* reader, lexer::SchemeLexer& l) {
+  ptr = l.Lex(reader);
+  return ptr;
+}
+
+TEST_F(SchemeLexerTest, IntegrateLex) {
+  textarrayformat::TextArrayReader textarray(*gen);
+
+  reader::StringReader sr(textarray.GetBlockAt(0));
+  reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
+  lexer::SchemeLexer lexer;
+
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_EQ(l->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kNumber);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kDatumComment);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kNumber);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kNumber);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kOpenParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kIdentifier);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kQuote);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kNumber);
+
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+  EXPECT_EQ(TestHelper(l, &reader, lexer)->type(), lexer::Token::kCloseParenthesis);
+}
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
index 6cf338f..37706c5 100755 (executable)
@@ -5,8 +5,9 @@
 #include "src/string_reader.h"
 #include "src/unicode.h"
 #include "lib/scoped_ptr.h"
+#include "lib/smart_ptr.h"
 #include "src/utf8_transcoder.h"
-#include "src/lexeme.h"
+#include "src/lexer/token.h"
 
 namespace textarrayformat = utility::textarrayformat;
 namespace lexer = utakata::lexer;
@@ -40,11 +41,12 @@ TEST_F(StringLexerTest, NormalStringLex) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::StringLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("hoge"));
   EXPECT_EQ(l->string().GetSize(), 4);
-  EXPECT_EQ(l->type(), lexer::Lexeme::kString);
+
+  EXPECT_EQ(l->type(), lexer::Token::kString);
 }
 
 TEST_F(StringLexerTest, InnerHexValueTest) {
@@ -54,8 +56,8 @@ TEST_F(StringLexerTest, InnerHexValueTest) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
 
   lexer::StringLexer lexer;
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("normaa"));
   EXPECT_EQ(l->string().GetSize(), 6);
 }
@@ -67,8 +69,8 @@ TEST_F(StringLexerTest, InitialWhitespaceRead) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::StringLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("start hoge"));
   EXPECT_EQ(l->string().GetSize(), 10);
 }
@@ -80,8 +82,8 @@ TEST_F(StringLexerTest, InitialWhitespaceRead2) {
   reader::EncodingReader reader(&sr, new transcoder::UTF8Transcoder);
   lexer::StringLexer lexer;
 
-  akebono::scoped_ptr<lexer::Lexeme> l(lexer.Lex(&reader));
-  EXPECT_TRUE(l.get() != NULL);
+  akebono::smart_ptr<lexer::Token> l(lexer.Lex(&reader));
+  EXPECT_TRUE(!l.is_null());
   EXPECT_TRUE(l->string() == unicode::Convert("starthuga"));
   EXPECT_EQ(l->string().GetSize(), 9);
 }