OSDN Git Service

syntax-treeの書き直しが概ね完了した。伴って、syntax_tree_test、及びparser_testの書き直しも行い、
authorderui <derutakayu@user.sourceforge.jp>
Tue, 1 Sep 2009 14:07:21 +0000 (23:07 +0900)
committerderui <derutakayu@user.sourceforge.jp>
Tue, 1 Sep 2009 14:07:21 +0000 (23:07 +0900)
テストが正常終了することを確認している。

12 files changed:
config.log
cons.cpp [deleted file]
cons.h [deleted file]
parser.cpp
parser.h
parser_handler.h
parser_status.h
test/parser_test.cpp
test/syntax_tree_test.cpp
tree.cpp
tree.h
tree_impl.h [deleted file]

index b403c83..2e27996 100644 (file)
@@ -561,3 +561,78 @@ target_alias=''
 #define HAVE_STDBOOL_H 1
 
 configure: exit 0
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status test/Makefile depfiles
+
+on dell_xps
+
+config.status:776: creating test/Makefile
+config.status:1050: executing depfiles commands
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status 
+
+on dell_xps
+
+config.status:776: creating Makefile
+config.status:776: creating test/Makefile
+config.status:776: creating config.h
+config.status:998: config.h is unchanged
+config.status:1050: executing depfiles commands
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status test/Makefile depfiles
+
+on dell_xps
+
+config.status:776: creating test/Makefile
+config.status:1050: executing depfiles commands
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by utakata config.status 0.0.1, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status test/Makefile depfiles
+
+on dell_xps
+
+config.status:776: creating test/Makefile
+config.status:1050: executing depfiles commands
diff --git a/cons.cpp b/cons.cpp
deleted file mode 100755 (executable)
index 157413c..0000000
--- a/cons.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#include "cons.h"
-#include "nullobject.h"
-#include "utf8_string.h"
-
-
-using namespace utakata::interpreter;
-using namespace utakata::utf8_string;
-
-struct Cons::pimpl
-{
-    smart_ptr<Object> car;
-    smart_ptr<Object> cdr;
-};
-
-Cons::Cons() : pimpl_(new Cons::pimpl)
-{
-    // 初期値としてNullObjectを設定する必要がある。
-    smart_ptr<Object> a(new NullObject());
-    smart_ptr<Object> d(new NullObject());
-    pimpl_->car = a;
-    pimpl_->cdr = d;
-}
-
-void Cons::setCar(smart_ptr<Object> obj)
-{
-    pimpl_->car = obj;
-}
-
-void Cons::setCdr(smart_ptr<Object> obj)
-{
-    pimpl_->cdr = obj;
-}
-
-smart_ptr<Object> Cons::car() const
-{
-    return pimpl_->car;
-}
-
-smart_ptr<Object> Cons::cdr() const
-{
-    return pimpl_->cdr;
-}
-
-smart_ptr<UTF8String> Cons::toValue()
-{
-    // 各オブジェクトから取得したデータを連結して返す。
-    smart_ptr<UTF8String> str(new UTF8String);
-    *str += "(";
-    *str += *pimpl_->car->toValue();
-
-    // cdrがNullObjectではない場合には、間に空白を入れて後を取得する。
-    if (!pimpl_->cdr->toValue()->empty())
-    {
-        *str += " ";
-        *str += *pimpl_->cdr->toValue();
-    }
-
-    *str += ")";
-    return str;
-}
-
-smart_ptr<Object> interpreter::conscat(smart_ptr<Object> c,
-                                       smart_ptr<Object> d)
-{
-    // cのcdrにdを設定したconsを生成して返すのみ。
-    // このconsは完全に新規なconsとなる。
-    smart_ptr<Cons> ret(new Cons);
-    c.setCar(c);
-    c.setCdr(d);
-    return smart_ptr<Object>().upcast(ret);
-}
diff --git a/cons.h b/cons.h
deleted file mode 100755 (executable)
index d2f88dc..0000000
--- a/cons.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef _CONS_H_
-#define _CONS_H_
-
-#include "smart_ptr.h"
-#include "object.h"
-
-namespace utakata {
-
-    namespace utf8_string {
-        class UTF8String;
-    };
-    
-    namespace interpreter {
-
-        class Cons : public Object
-        {
-            // オブジェクトから派生したConsを構築するための
-            // オブジェクト。
-            // これ自体も当然オブジェクトであるので、Objectより派生する。
-            // このオブジェクトのデータ値は()で表現される。
-            // TypeHashの元となる名前は"Cons"とする。
-        public:
-            Cons();
-            virtual ~Cons(){}
-
-            bool enableChange() const {return false;}
-            smart_ptr<utf8_string::UTF8String> toValue();
-
-            // car/cdrの設定、取得を行う。
-            void setCar(smart_ptr<Object> obj);
-            void setCdr(smart_ptr<Object> obj);
-            
-            smart_ptr<Object>& car() {
-                return const_cast<smart_ptr<Object>& >(
-                    static_cast<const Cons*>(this)->car());
-            }
-            smart_ptr<Object> car() const;
-            smart_ptr<Object>& cdr() {
-                return const_cast<smart_ptr<Object>& >(
-                    static_cast<const Cons*>(this)->cdr());
-            }
-            smart_ptr<Object> cdr() const;
-
-        private:
-
-            struct pimpl;
-            smart_ptr<pimpl> pimpl_;
-
-        };
-
-        // cのcdrにdを設定したconsを新たに生成して返す。
-        smart_ptr<Object> conscat(smart_ptr<Object>& c, const smart_ptr<Object> d);
-    };
-
-};
-
-#endif /* _CONS_H_ */
index d5954b8..4cbad34 100755 (executable)
@@ -14,83 +14,103 @@ using namespace utakata::interpreter;
 using namespace utakata::parser;
 using namespace utakata::lexeme;
 
-parser::DatumException::DatumException (std::string str) : str_()
+parser::DatumException::DatumException(std::string str) : str_()
 {
     // エラーメッセージを定義する。
     std::stringstream ss;
     ss << "datum error ! -- message : [" << str << "]" << std::endl;
-    str_ = ss.str ();
+    str_ = ss.str();
 }
 
-const char* parser::DatumException::what () const throw ()
+const char* parser::DatumException::what() const throw()
 {
-    return str_.c_str ();
+    return str_.c_str();
 }
 
 ////////////////////////////
 // Parser Implementations //
 ////////////////////////////
 
-parser::Parser::Parser (smart_ptr<lexer::Lexer> l) : lexer_(l),
+parser::Parser::Parser(smart_ptr<lexer::Lexer> l) : lexer_(l),
                                                      handler_()
 {
     // 初期状態用ハンドラの設定
     std::pair<PARSERSTATUS, smart_ptr<IParserHandler> > p;
     p.first = PS_INIT;
-    p.second.add (new InitHandler);
-    handler_.insert (p);
+    p.second.add(new InitHandler);
+    handler_.insert(p);
 
     // リスト内部用ハンドラの設定
     p.first = PS_LIST_CAR;
-    p.second.add (new ListHandler);
-    handler_.insert (p);
+    p.second.add(new ListCarHandler);
+    handler_.insert(p);
 
     p.first = PS_LIST_CDR;
-    p.second.add (new ListHandler);
-    handler_.insert (p);
+    p.second.add(new ListCdrHandler);
+    handler_.insert(p);
 
     // .内用ハンドラの設定
     p.first = PS_AFTER_DOT;
-    p.second.add (new DotHandler);
-    handler_.insert (p);
+    p.second.add(new DotHandler);
+    handler_.insert(p);
+
+    p.first = PS_END_DOT;
+    p.second.add(new DotEndHandler);
+    handler_.insert(p);
 
     // abbreviation 用ハンドラの設定
     p.first = PS_ABBREVIATION;
-    p.second.add (new AbbrevHandler);
-    handler_.insert (p);
+    p.second.add(new AbbrevHandler);
+    handler_.insert(p);
+
+    // error 用のハンドラの設定
+    p.first = PS_ERROR;
+    p.second.add(new ErrorHandler);
+    handler_.insert(p);
 }
 
-smart_ptr<syntax::Tree> parser::Parser::parse (smart_ptr<utf8::UTF8InputStream>& strm)
+smart_ptr<syntax::Tree> parser::Parser::parse(smart_ptr<utf8::UTF8InputStream>& strm)
 {
     HandlerData data;
     data.main.add(new syntax::Tree());
     data.status.push(PS_INIT);
-    data.stack.push(data.main->begin());
+    data.stack.push(data.main);
     
-    while (! (data.lexm = lexer_->lex (strm)).isNull ()) {
-        if (data.lexm->getID () == lexeme::LexemeID::eos)
+    while(true) {
+
+        if(data.status.top() != PS_ERROR)
         {
-            break;
+            data.lexm = lexer_->lex(strm);
+            if(data.lexm.isNull() ||
+                data.lexm->getID() == lexeme::LexemeID::eos)
+            {
+                break;
+            }
+            // 基本的にすべてハンドラに任せる。
+            handler_[data.status.top()]->exec(data);
+        }
+        else
+        {
+            // ERROR だったら、強制的にハンドラを回してループから抜ける。
+            handler_[data.status.top()]->exec(data);
         }
-
-        // 基本的にすべてハンドラに任せる。
-        handler_[data.status.top ()]->exec (data);
     }
 
-    // 終端に逹した時点で、 stack にデータが殘っていたら例外
+    // stackのtopにはmainが殘ったままなので、data.stackのtopを追加してやる
     
-//     if (stack.size() != 1)
-//     {
-//         throw DatumException ("() の整合性が取れていません");
-//     }
+    if (data.stack.size() == 2)
+    {
+        data.main->push_back(data.stack.top()->begin(), data.stack.top()->end(),
+                             syntax::makeCompoundDatum(syntax::DatumID::list));
+    }
 
     return data.main;
 }
 
-bool parser::isAbbrev (smart_ptr<lexeme::ILexeme> l)
+bool parser::isAbbrev(smart_ptr<lexeme::ILexeme> l)
 {
     // abbreviation かどうかを判別する。
-    switch (l->getID ().toEnum ())
+    switch(l->getID().toEnum())
     {
     case lexeme::LexemeID::BACKQUOTE:        return true;
     case lexeme::LexemeID::QUOTE:            return true;
@@ -105,9 +125,9 @@ bool parser::isAbbrev (smart_ptr<lexeme::ILexeme> l)
     }
 }
 
-syntax::DatumID parser::toDatumType (lexeme::LexemeID id)
+syntax::DatumID parser::toDatumType(lexeme::LexemeID id)
 {
-    switch (id.toEnum ())
+    switch(id.toEnum())
     {
     case lexeme::LexemeID::STRING:
         return syntax::DatumID::string;
@@ -131,48 +151,41 @@ syntax::DatumID parser::toDatumType (lexeme::LexemeID id)
 bool InitHandler::exec_(HandlerData& data)
 {
     // 初期状態の解釈処理を行う。
-    if (data.lexm->getID () == lexeme::LexemeID::openParenthesis)
+    if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
     {
-        // 開き括弧である場合、もはや main をツリーに登録する必要も無く、
-        // iterator を stack するだけでよい。 stack した iterator は、原則として
-        // ) が来ないと取り外せない。
-        data.stack.push (syntax::Tree::iterator());
-        data.status.push(PS_LIST_CDR);
-        data.status.push (PS_LIST_CAR);
+        // 開き括弧である場合、新しい tree をスタックの top に設定する。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        data.status.push(PS_LIST_CAR);
     }
-    else if (data.lexm->getID () == lexeme::LexemeID::string ||
-             data.lexm->getID () == lexeme::LexemeID::number ||
-             data.lexm->getID () == lexeme::LexemeID::identifier ||
-             data.lexm->getID () == lexeme::LexemeID::charactor ||
-             data.lexm->getID () == lexeme::LexemeID::boolean)
+    else if(data.lexm->getID() == lexeme::LexemeID::string ||
+             data.lexm->getID() == lexeme::LexemeID::number ||
+             data.lexm->getID() == lexeme::LexemeID::identifier ||
+             data.lexm->getID() == lexeme::LexemeID::charactor ||
+             data.lexm->getID() == lexeme::LexemeID::boolean)
     {
         // それぞれの場合、 lexeme_datum として扱われる。
-        // stack.top の iterator に cons する。
-        syntax::Tree::iterator it = data.stack.top(); data.stack.pop();
-        it = data.main->cons (it, syntax::makeLexemeDatum (
-                                  literal::generateLiteral (data.lexm),
-                                  toDatumType (data.lexm->getID ())));
-        data.stack.push(it);
+        // stack の top に push_back にする。
+        data.stack.top()->push_back(syntax::makeLexemeDatum(
+                                  literal::generateLiteral(data.lexm),
+                                  toDatumType(data.lexm->getID())));
         // status を pop する。
-        data.status.pop ();
+        data.status.pop();
     }
-    else if (isAbbrev (data.lexm))
+    else if(isAbbrev(data.lexm))
     {
-        // abbreviaition である場合でも、これはまったくの同様
-        // である。ただし、 abbreviation は正確には conpound datum を構成
-        // するため、新規イテレータを導入する必要がある。
-        syntax::Tree::iterator it2;
-        it2 = data.main->cons (it2, syntax::makeAbbreviation (
-                                   literal::generateLiteral (data.lexm)));
-        data.stack.push (it2);
+        // abbreviation である場合には、 list に内包する必要があるため、
+        // 新規に作成する。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        data.stack.top()->push_back(syntax::makeAbbreviation(
+                                  literal::generateLiteral(data.lexm)));
 
         // status stack に、 PS_ABBREVIATION と PS_INIT を積む。
-        data.status.push (PS_ABBREVIATION);
-        data.status.push (PS_INIT);
+        data.status.push(PS_ABBREVIATION);
+        data.status.push(PS_INIT);
     }
     else
     {
-        throw DatumException ("datum の開始記号ではありません");
+        throw DatumException("datum の開始記号ではありません");
     }
 
     return true;
@@ -180,84 +193,132 @@ bool InitHandler::exec_(HandlerData& data)
 
 // List 内部処理のハンドリング
 
-bool ListHandler::exec_(HandlerData& data)
+bool ListCarHandler::exec_(HandlerData& data)
 {
-    // list の内部である場合。
-    if (data.lexm->getID () == lexeme::LexemeID::openParenthesis)
+    // list の開始部分である場合。
+    if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
     {
         // 更に追加して積む。
-        data.stack.push (syntax::Tree::iterator());
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
         // status に再度積む。
+        data.status.push(PS_LIST_CAR);
+    }
+    else if(data.lexm->getID() == lexeme::LexemeID::closeParenthesis)
+    {
+        // car の時点で) が来たら、この時点で終了としておくしかない。
+        smart_ptr<syntax::Tree> it = data.stack.top(); data.stack.pop();
+        data.stack.top()->push_back(it->begin(), it->end(),
+                                    syntax::makeCompoundDatum(syntax::DatumID::list));
+        
+        data.status.pop();
+    }
+    else if(data.lexm->getID() == lexeme::LexemeID::string ||
+             data.lexm->getID() == lexeme::LexemeID::number ||
+             data.lexm->getID() == lexeme::LexemeID::identifier ||
+             data.lexm->getID() == lexeme::LexemeID::charactor ||
+             data.lexm->getID() == lexeme::LexemeID::boolean)
+    {
+        //push_back して、その後に PS_LIST_CDR をセットしておく。
+
+        data.stack.top()->push_back(syntax::makeLexemeDatum(
+                                        literal::generateLiteral(data.lexm),
+                                        toDatumType(data.lexm->getID())));
+        data.status.pop();
         data.status.push(PS_LIST_CDR);
-        data.status.push (PS_LIST_CAR);
+    }
+    else if(isAbbrev(data.lexm))
+    {
+        // abbreviation を判別して status を返す。
+        // この場合、新規にツリーを作成して、再度設定を行う。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        data.stack.top()->push_back(syntax::makeAbbreviation(
+                                        literal::generateLiteral(data.lexm)));
 
+        // status stack に、 PS_ABBREVIATION と PS_INIT を積む。
+        data.status.push(PS_ABBREVIATION);
+        data.status.push(PS_INIT);
     }
-    else if (data.lexm->getID () == lexeme::LexemeID::closeParenthesis)
+    else
     {
-        // stack の top を取り外す。
-        
-        syntax::Tree::iterator it = data.stack.top(); data.stack.pop();
-        syntax::Tree::iterator it2 = data.stack.top(); data.stack.pop();
+        // 上記以外は許容しない。
+        data.status.push(PS_ERROR);
+    }
 
-        // 更に stack の top に cons する。
-        it2 = data.main->cons (it2, it);
-        data.stack.push(it2);
-        
-        // topがcarである場合には、2個popし、cdrである場合は一つだけ
-        // popする。
-        if (data.status.top() == PS_LIST_CAR)
-        {
-            data.status.pop(); data.status.pop();
-        }
-        else if (data.status.top() == PS_LIST_CDR)
-        {
-            data.status.pop();
-        }
-        else
-        {
-            throw DatumException ("構文異常です");
-        }
+    return true;
+}
+
+bool ListCdrHandler::exec_(HandlerData& data)
+{
+    // list の開始部分以降である場合。
+    if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
+    {
+        // 更に追加して積む。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        // status に再度積む。
+        data.status.push(PS_LIST_CAR);
     }
-    else if (data.lexm->getID () == lexeme::LexemeID::string ||
-             data.lexm->getID () == lexeme::LexemeID::number ||
-             data.lexm->getID () == lexeme::LexemeID::identifier ||
-             data.lexm->getID () == lexeme::LexemeID::charactor ||
-             data.lexm->getID () == lexeme::LexemeID::boolean)
+    else if(data.lexm->getID() == lexeme::LexemeID::closeParenthesis)
     {
-        // cons するだけ。
-        // ただし、consした後のiteratorをちゃんと入れ替えておかないと
-        // ならない。
-        syntax::Tree::iterator it = data.stack.top(); data.stack.pop();
-        it  = data.main->cons(it, syntax::makeLexemeDatum (
-                                  literal::generateLiteral (data.lexm),
-                                  toDatumType (data.lexm->getID ())));
-        data.stack.push(it);
+        // 現在の stack の top を、下の Tree に push_back する。
+        smart_ptr<syntax::Tree> it = data.stack.top(); data.stack.pop();
+        data.stack.top()->push_back(it->begin(), it->end(),
+                                    syntax::makeCompoundDatum(syntax::DatumID::list));
+        data.status.pop();
     }
-    else if (isAbbrev (data.lexm))
+    else if(data.lexm->getID() == lexeme::LexemeID::string ||
+             data.lexm->getID() == lexeme::LexemeID::number ||
+             data.lexm->getID() == lexeme::LexemeID::identifier ||
+             data.lexm->getID() == lexeme::LexemeID::charactor ||
+             data.lexm->getID() == lexeme::LexemeID::boolean)
+    {
+        //push_back するが、) が来るまでは status を pop する必要は無い。
+        data.stack.top()->push_back(syntax::makeLexemeDatum(
+                                        literal::generateLiteral(data.lexm),
+                                        toDatumType(data.lexm->getID())));
+    }
+    else if(isAbbrev(data.lexm))
     {
         // abbreviation を判別して status を返す。
         // この場合、新規にツリーを作成して、再度設定を行う。
-        syntax::Tree::iterator it2;
-        it2 = data.main->cons(it2, syntax::makeAbbreviation (
-                                  literal::generateLiteral (data.lexm)));
-        data.stack.push (it2);
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        data.stack.top()->push_back(syntax::makeAbbreviation(
+                                        literal::generateLiteral(data.lexm)));
 
         // status stack に、 PS_ABBREVIATION と PS_INIT を積む。
-        data.status.push (PS_ABBREVIATION);
-        data.status.push (PS_INIT);
+        data.status.push(PS_ABBREVIATION);
     }
-    else if (data.lexm->getID () == lexeme::LexemeID::dot)
+    else if(data.lexm->getID() == lexeme::LexemeID::dot)
     {
-        // list_car の時に.が来たら処理が終了できなくなる。
-        if (data.status.top() == PS_LIST_CAR)
-        {
-            throw DatumException ("リストの先頭に . が設定されることは出来ません");
-        }
-        else
-        {
-            // cdrの場合には、そのまま設定させることができる。
-        }
+        // .が来た場合、これは許容される。
+        // この場合、.が完了した時点でリストが終了していなければならないため、
+        // after_dot の後には、 end_list ハンドラが設定される。
+        data.status.push(PS_AFTER_DOT);
+    }
+    else
+    {
+        // 上記以外は許容しない。
+        data.status.push(PS_ERROR);
+    }
+
+    return true;
+}
 
+bool DotEndHandler::exec_(HandlerData& data)
+{
+    // .後の) を待つ部分のハンドラ。
+    // このハンドラでは、) 以外が来た場合にはすべて構文エラーとなる。
+    if(data.lexm->getID() == lexeme::LexemeID::closeParenthesis)
+    {
+        // 現在の stack の top を、下の Tree に push_back する。
+        smart_ptr<syntax::Tree> it = data.stack.top(); data.stack.pop();
+        data.stack.top()->push_back(it->begin(), it->end(),
+                                    syntax::makeCompoundDatum(syntax::DatumID::list));
+        data.status.pop();
+    }
+    else
+    {
+        // 上記以外は許容しない。
+        data.status.push(PS_ERROR);
     }
 
     return true;
@@ -268,49 +329,47 @@ bool ListHandler::exec_(HandlerData& data)
 bool DotHandler::exec_(HandlerData& data)
 {
     // .の後である場合。
-    if (data.lexm->getID () == lexeme::LexemeID::openParenthesis)
-    {
-        // 開き括弧である場合
-        data.stack.push(syntax::Tree::iterator());
-        
-        data.status.push(PS_LIST_CDR);
-        data.status.push (PS_LIST_CAR);
-    }
-    else if (data.lexm->getID () == lexeme::LexemeID::string ||
-             data.lexm->getID () == lexeme::LexemeID::number ||
-             data.lexm->getID () == lexeme::LexemeID::identifier ||
-             data.lexm->getID () == lexeme::LexemeID::charactor ||
-             data.lexm->getID () == lexeme::LexemeID::boolean)
+    data.status.pop();
+    if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
     {
-        // リテラルの場合、単純に戻るのみとなる。
-        syntax::Tree::iterator it = data.stack.top(); data.stack.pop();
-        it = data.main->cons(it, syntax::makeLexemeDatum(
-                                 literal::generateLiteral(data.lexm),
-                                 toDatumType(data.lexm->getID())));
-        data.status.pop ();
+        // 更に追加して積む。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        // status に再度積む。
+        data.status.push(PS_END_DOT);
+        data.status.push(PS_LIST_CAR);
     }
-    else if (data.lexm->getID () == lexeme::LexemeID::closeParenthesis)
+    else if(data.lexm->getID() == lexeme::LexemeID::string ||
+             data.lexm->getID() == lexeme::LexemeID::number ||
+             data.lexm->getID() == lexeme::LexemeID::identifier ||
+             data.lexm->getID() == lexeme::LexemeID::charactor ||
+             data.lexm->getID() == lexeme::LexemeID::boolean)
     {
-        // .の直後の)は不正。
-        throw DatumException (".の直後に)が存在しています");
+        // push_back した後、この時点で after_dot が完了しているため、
+        // end_dot に移動する。
+
+        data.stack.top()->push_back(syntax::makeLexemeDatum(
+                                        literal::generateLiteral(data.lexm),
+                                        toDatumType(data.lexm->getID())));
+        data.status.push(PS_END_DOT);
     }
-    else if (isAbbrev (data.lexm))
+    else if(isAbbrev(data.lexm))
     {
         // abbreviation を判別して status を返す。
         // この場合、新規にツリーを作成して、再度設定を行う。
-        syntax::Tree::iterator it2;
-        it2 = data.main->cons (it2, syntax::makeAbbreviation (
-                                   literal::generateLiteral (data.lexm)));
-        data.stack.push (it2);
-
-        // status stack に、 PS_ABBREVIATION と PS_INIT を積む。
-        data.status.push (PS_ABBREVIATION);
-        data.status.push (PS_INIT);
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        data.stack.top()->push_back(syntax::makeAbbreviation(
+                                        literal::generateLiteral(data.lexm)));
+
+        // status stack に、 PS_END_DOT まで含めて、
+        // PS_ABBREVIATION と PS_INIT を積む。
+        data.status.push(PS_END_DOT);
+        data.status.push(PS_ABBREVIATION);
+        data.status.push(PS_INIT);
     }
     else
     {
-        // .の直後の.は当然不正
-        throw DatumException (".の直後に.が存在しています");
+        // 上記以外はすべて不正となる。
+        data.status.push(PS_ERROR);
     }
 
     return true;
@@ -320,18 +379,73 @@ bool DotHandler::exec_(HandlerData& data)
 
 bool AbbrevHandler::exec_(HandlerData& data)
 {
-    // この場合、現在stackの最上段に存在しているiteratorをpopし、
-    // その下のiteratorに対してconsする、というほぼ同様の処理が行われる。
-    syntax::Tree::iterator it = data.stack.top(); data.stack.pop();
+    // この場合、 top の一つ下が、 abbrev が属する list の親になっているため、
+    // この場合でも単純に list として設定できる。
+    if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
+    {
+        // 更に追加して積む。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        // status に再度積む。
+        data.status.push(PS_LIST_CAR);
+    }
+    else if(data.lexm->getID() == lexeme::LexemeID::string ||
+            data.lexm->getID() == lexeme::LexemeID::number ||
+            data.lexm->getID() == lexeme::LexemeID::identifier ||
+            data.lexm->getID() == lexeme::LexemeID::charactor ||
+            data.lexm->getID() == lexeme::LexemeID::boolean)
+    {
+        //push_back するが、) が来るまでは status を pop する必要は無い。
+        data.stack.top()->push_back(syntax::makeLexemeDatum(
+                                        literal::generateLiteral(data.lexm),
+                                        toDatumType(data.lexm->getID())));
+    }
+    else if(isAbbrev(data.lexm))
+    {
+        // abbreviation を判別して status を返す。
+        // この場合、新規にツリーを作成して、再度設定を行う。
+        data.stack.push(smart_ptr<syntax::Tree>(new syntax::Tree()));
+        data.stack.top()->push_back(syntax::makeAbbreviation(
+                                        literal::generateLiteral(data.lexm)));
+
+        // status stack に、 PS_ABBREVIATION と PS_INIT を積む。
+        data.status.push(PS_ABBREVIATION);
+    }
+    else if(data.lexm->getID() == lexeme::LexemeID::dot)
+    {
+        // .が来た場合、これは許容される。
+        // この場合、.が完了した時点でリストが終了していなければならないため、
+        // after_dot の後には、 end_list ハンドラが設定される。
+        data.status.push(PS_AFTER_DOT);
+    }
+    else
+    {
+        // 上記以外は許容しない。
+        data.status.push(PS_ERROR);
+    }
 
-    // itをconsする。この時点で、通常とほとんど同様である状態になる。
-    syntax::Tree::iterator it2 = data.stack.top(); data.stack.pop();
     
-    it2 = data.main->cons(it2, it);
-    data.stack.push(it2);
+    if (data.stack.top()->size() == 3)
+    {
+        smart_ptr<syntax::Tree> it = data.stack.top(); data.stack.pop();
+        data.stack.top()->push_back(it->begin(), it->end(),
+                                    syntax::makeCompoundDatum(syntax::DatumID::list));
 
-    // 最後にpopしておけばそれで問題無い。
-    data.status.pop();
+        // 最後に pop しておけばそれで問題無い。
+        data.status.pop();
+    }
+
+    return true;
+}
+
+// syntax error のハンドリング
+
+bool ErrorHandler::exec_(HandlerData& data)
+{
+    // 基本的にはエラーのハンドリングを行うだけ。
+    // 一応発生した前後の位置と発生した lexeme くらいは表示したいかな。
+    std::stringstream ss;
+    ss << "syntax error" << data.stack.top()->size() << data.stack.top()->begin()->second->toValue()->toStr();
+    throw DatumException(ss.str());
 
     return true;
 }
index 33b5831..2a589dc 100755 (executable)
--- a/parser.h
+++ b/parser.h
@@ -85,12 +85,13 @@ namespace utakata {
 
         };
 
-        class ListHandler : public IParserHandler
+        // <list>に対応するものだけは、carとcdrでハンドラが分離している。
+        class ListCarHandler : public IParserHandler
         {
             // PS_LIST_CARである間に対応するハンドラ
         public:
-            ListHandler() {}
-            virtual ~ListHandler() {}
+            ListCarHandler() {}
+            virtual ~ListCarHandler() {}
 
         private:
 
@@ -98,6 +99,21 @@ namespace utakata {
 
         };
 
+        
+        class ListCdrHandler : public IParserHandler
+        {
+            // PS_LIST_CDRである間に対応するハンドラ
+        public:
+            ListCdrHandler() {}
+            virtual ~ListCdrHandler() {}
+
+        private:
+
+            bool exec_(HandlerData& data);
+
+        };
+
+
         class DotHandler : public IParserHandler
         {
             // PS_AFTER_DOTに対応するハンドラ
@@ -111,6 +127,21 @@ namespace utakata {
 
         };
 
+        // <list>に対応するものだけは、carとcdrでハンドラが分離している。
+        class DotEndHandler : public IParserHandler
+        {
+            // PS_END_DOTに対応するハンドラ。
+        public:
+            DotEndHandler() {}
+            virtual ~DotEndHandler() {}
+
+        private:
+
+            bool exec_(HandlerData& data);
+
+        };
+
+
         class AbbrevHandler : public IParserHandler
         {
             // PS_ABBREVIATIONに対応するハンドラ
@@ -124,6 +155,20 @@ namespace utakata {
 
         };
 
+        class ErrorHandler : public IParserHandler
+        {
+            // PS_ERRORをハンドリングする。実際にはエラーを通告する
+            // のみ。
+        public:
+            ErrorHandler() {}
+            virtual ~ErrorHandler() {}
+            
+        private:
+
+            bool exec_(HandlerData& data);
+
+        };
+
     };
 
 };
index 6644d0a..b3a1e2b 100755 (executable)
@@ -15,21 +15,12 @@ namespace utakata {
     namespace parser {
 
         typedef std::stack<smart_ptr<syntax::Tree> > treestack;
-        typedef std::stack<syntax::Tree::iterator> iteratorstack;
 
-        struct StackData
-        {
-            // HandlerDataのtreestackに累積されるデータ
-            smart_ptr<syntax::Tree> cur_tree;
-            syntax::Tree::iterator cur_itr
-        };
-        
         struct HandlerData
         {
             smart_ptr<syntax::Tree> main;
             smart_ptr<lexeme::ILexeme> lexm;
             treestack stack;
-            syntax::Tree::iterator current; 
             std::stack<PARSERSTATUS> status;
         };
         
index 2c692eb..a7a972b 100755 (executable)
@@ -15,6 +15,10 @@ namespace utakata {
             PS_VECTOR_END          = 16, /* #(と対応した) */
             PS_BYTEVECTOR_START    = 17, /* #vu8( */
             PS_BYTEVECTOR_END      = 18, /* #vu8(と対応した) */
+            PS_ERROR,                    // 構文異常が発生した場合に設定される。
+                                         // これが設定されている場合、lexmの読み出しは進まず、
+                                         // その時点で終了することになる。
+            PS_END_DOT,                 // listの終了時点を表す。)以外は許容されない。
         };
     };
 };
index 9271aaa..5c22acd 100755 (executable)
@@ -20,6 +20,8 @@
 using namespace std;
 using namespace utakata;
 
+
+
 bool parser_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
 {
     std::stringstream ss;
@@ -29,8 +31,11 @@ bool parser_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
     ss << "(+ (- 12 \"hoge\") 24)" << endl;
     ss << "==========" << endl;
     ss << "((- 12 \"hoge\") '24)" << endl;
+    ss << "==========" << endl;
+    ss << "(define hoge (lambda () (- 12 24)))" << endl;
 
     textarrayformat::TextArrayReader reader(ss);
+
     smart_ptr<istream> formats(new stringstream(reader.get(2)));
     smart_ptr<utakata::utf8::UTF8InputStream> st;
     st.add(new utakata::utf8::UTF8InputStream(formats));
@@ -42,24 +47,116 @@ bool parser_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
     utakata::parser::Parser p(lexer);
     smart_ptr<syntax::Tree> t = p.parse(st);
     syntax::Tree::iterator it = t->begin();
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST, "list error1");
+    it = t->in_compound_begin(it);
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST, "list error by compound");
+    syntax::Tree::iterator it2 = t->in_compound_begin(it);
+    asserter->check(it2->first.toEnum(), syntax::DatumID::SYMBOL, "symbol error2");
 
-    asserter->check(t->car(it)->first.toEnum(), syntax::DatumID::LIST, "list error1");
-    it = t->car(it);
-    std::cout << it->second->toValue()->toStr() << std::endl;
-    
-    asserter->check(it->first.toEnum(), syntax::DatumID::NUMBER, "number error2");
-    syntax::Tree::iterator it2 = t->car(it);
-    asserter->check(t->car(it2)->first.toEnum(), syntax::DatumID::LIST, "list error2");
+    ++it2;
+    asserter->check(it2->first.toEnum(), syntax::DatumID::NUMBER, "number error2");
+    ++it2;
+    asserter->check(it2->first.toEnum(), syntax::DatumID::STRING, "string error");
+
+    // この次はnilとなっている。
+
+    ++it;
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST, "list error");
+    it2 = t->in_compound_begin(it);
+    asserter->check(it2->first.toEnum(), syntax::DatumID::ABBREVIATIONS, "abbrev error");
+    ++it2;
+    asserter->check(it2->first.toEnum(), syntax::DatumID::NUMBER, "number error");
     
     return asserter->isOk();
 }
 
+bool parser_test2(smart_ptr<simpletest::SimpleTestAsserter> asserter)
+{
+    // ss << "(define hoge (lambda () (- 12 24)))" << endl;
+    std::stringstream ss;
+    ss << "==========" << endl;
+    ss << "(+ 12 24)" << endl;
+    ss << "==========" << endl;
+    ss << "(+ (- 12 \"hoge\") 24)" << endl;
+    ss << "==========" << endl;
+    ss << "((- 12 \"hoge\") '24)" << endl;
+    ss << "==========" << endl;
+    ss << "(define hoge (lambda () (- 12 24)))" << endl;
+
+    textarrayformat::TextArrayReader reader(ss);
+
+    smart_ptr<istream> formats(new stringstream(reader.get(3)));
+    smart_ptr<utakata::utf8::UTF8InputStream> st(new utakata::utf8::UTF8InputStream(formats));
+    smart_ptr<utakata::lexer::Lexer> lexer(new utakata::lexer::Lexer());
+    utakata::parser::Parser p(lexer);
+    smart_ptr<syntax::Tree> t = p.parse(st);
+    syntax::Tree::iterator it = t->begin();
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST, "list error1");
+
+    it = t->in_compound_begin(it);
+    asserter->check(it->first.toEnum(), syntax::DatumID::SYMBOL, "not define");
+    ++it;
+    asserter->check(it->first.toEnum(), syntax::DatumID::SYMBOL, "not hoge");
+
+    ++it;
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST, "not lambda list");
+    syntax::Tree::iterator it2 = t->in_compound_begin(it);
+    asserter->check(it2->first.toEnum(), syntax::DatumID::SYMBOL, "not lambda");
+    asserter->check((++it2)->first.toEnum(), syntax::DatumID::LIST, "not ()");
+
+    syntax::Tree::iterator it3 = t->in_compound_begin(it2);
+    asserter->check(it3->first.toEnum(), syntax::DatumID::NIL, "not in ()");
+
+    asserter->check((++it2)->first.toEnum(), syntax::DatumID::LIST, "not body form");
+    it2 = t->in_compound_begin(it2);
+    asserter->check(it2->first.toEnum(), syntax::DatumID::SYMBOL, "not +");
+    asserter->check((++it2)->first.toEnum(), syntax::DatumID::NUMBER, "not 12");
+    asserter->check((++it2)->first.toEnum(), syntax::DatumID::NUMBER, "not 24");
+    return asserter->isOk();
+}
+
+bool parser_test3(smart_ptr<simpletest::SimpleTestAsserter> asserter)
+{
+    // ss << "(define hoge (lambda () (- 12 24)))" << endl;
+    std::stringstream ss;
+    ss << "==========" << endl;
+    ss << "(+ 12 24)" << endl;
+    ss << "==========" << endl;
+    ss << "(+ (- 12 \"hoge\") 24)" << endl;
+    ss << "==========" << endl;
+    ss << "((- 12 \"hoge\") '24)" << endl;
+    ss << "==========" << endl;
+    ss << ",(hoge)" << endl;
+
+    textarrayformat::TextArrayReader reader(ss);
+
+    smart_ptr<istream> formats(new stringstream(reader.get(3)));
+    smart_ptr<utakata::utf8::UTF8InputStream> st(new utakata::utf8::UTF8InputStream(formats));
+    smart_ptr<utakata::lexer::Lexer> lexer(new utakata::lexer::Lexer());
+    utakata::parser::Parser p(lexer);
+    smart_ptr<syntax::Tree> t = p.parse(st);
+    syntax::Tree::iterator it = t->begin();
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST, "list error");
+
+    syntax::Tree::iterator it2 = t->in_compound_begin(it);
+
+    asserter->check(it2->first.toEnum(), syntax::DatumID::ABBREVIATIONS, "not abbrev");
+    asserter->check((++it2)->first.toEnum(), syntax::DatumID::LIST, "not list");
+
+    it2 = t->in_compound_begin(it2);
+    asserter->check(it2->first.toEnum(), syntax::DatumID::SYMBOL, "not hoge");
+
+    return asserter->isOk();
+}
+
 int main(int argc, char *argv[])
 {
     simpletest::SimpleTestSuite suite("parser test");
     suite.addTester(sfcr::screate(parser_test, suite.getAsserter()));
-//     suite.addTester(sfcr::screate(parser_test2, suite.getAsserter()));
-//     suite.addTester(sfcr::screate(parser_test3, suite.getAsserter()));
+    suite.addTester(sfcr::screate(parser_test2, suite.getAsserter()));
+    suite.addTester(sfcr::screate(parser_test3, suite.getAsserter()));
     suite.run();
     return 0;
 }
index 7db27b3..2991258 100755 (executable)
@@ -57,7 +57,7 @@ bool syntax_tree_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
     // 他のcompound datumを設定するためには、このようにして設定しなければならない。
     // iteratorを範囲をpush_backした場合には、iteratorはcompound datumとして
     // 認識されるため、型を表すdatumを渡す必要がある。
-    t->push_back(t2->begin(), t2->end(), syntax::makeCompoundDatum(syntax::DatumID::LIST));
+    t->push_back(t2.begin(), t2.end(), syntax::makeCompoundDatum(syntax::DatumID::list));
     
     // beginでは、現在Treeが保持しているトップが取得される。
     syntax::Tree::iterator lo = t->begin();
@@ -66,7 +66,7 @@ bool syntax_tree_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
     asserter->checkOnly(lo->first.toEnum(), syntax::DatumID::LIST);
 
     // 内部はこれで取得可能。lo2はlistの内部のみを巡回することができる。
-    syntax::Tree::iterator lo2 = t->in_compound(lo);
+    syntax::Tree::iterator lo2 = t->in_compound_begin(lo);
 
     // Literalオブジェクトの表面的なデータ型としては、Objectと同様。
     asserter->checkOnly(lo2->second->toValue()->toStr(), "hoge");
@@ -90,96 +90,102 @@ bool syntax_tree_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
     return asserter->isOk();
 }
 
-// bool syntax_tree_test2(smart_ptr<simpletest::SimpleTestAsserter> asserter)
-// {
-//     // 通常通り利用すると、かなり面倒なので、解析の際に各種省略系を使う
-//     // テスト。
-//     std::stringstream ss;
-//     ss << "==========" << endl;
-//     ss << ",@(hoge 12 `(hage) 'huga #f #t)" << endl;
-
-//     textarrayformat::TextArrayReader reader(ss);
-//     smart_ptr<istream> formats(new stringstream(reader.get()));
-//     smart_ptr<utakata::utf8::UTF8InputStream> st;
-//     st.add(new utakata::utf8::UTF8InputStream(formats));
+bool syntax_tree_test2(smart_ptr<simpletest::SimpleTestAsserter> asserter)
+{
+    // 通常通り利用すると、かなり面倒なので、解析の際に各種省略系を使う
+    // テスト。
+    std::stringstream ss;
+    ss << "==========" << endl;
+    ss << ",@(hoge 12 `(hage) 'huga #f #t)" << endl;
+
+    textarrayformat::TextArrayReader reader(ss);
+    smart_ptr<istream> formats(new stringstream(reader.get()));
+    smart_ptr<utakata::utf8::UTF8InputStream> st;
+    st.add(new utakata::utf8::UTF8InputStream(formats));
     
-//     utakata::lexer::Lexer lexer;
-
-//     smart_ptr<lexeme::ILexeme> m(lexer.lex(st));
-//     smart_ptr<syntax::Tree> root(new syntax::Tree);
-//     smart_ptr<syntax::Tree> t(root);
-//     std::stack<smart_ptr<syntax::Tree> > s;
-
-//     // 最初から,@なので、compoundと判断し、Treeを設定する。
-//     s.push(t);
-//     t.add(new syntax::Tree);
-//     t->push_cons(syntax::makeAbbreviation(
-//                     literal::generateLiteral(m)));
-
-//     // (なので、再度pushして再生成。
-//     lexer.lex(st);
-
-//     s.push(t);
-//     t.add(new syntax::Tree);
-//     m = lexer.lex(st);
-//     // symbol,numberをそれぞれ設定するつもりで。
-//     t->push_cons(syntax::makeLexemeDatum(
-//                     literal::generateLiteral(m),
-//                     syntax::toDatumType(m)));
-//     m = lexer.lex(st);
-//     t->push_cons(syntax::makeLexemeDatum(
-//                     literal::generateLiteral(m),
-//                     syntax::toDatumType(m)));
-
-//     s.push(t);
-//     t.add(new syntax::Tree);
-//     t->push_cons(syntax::makeAbbreviation(
-//                      literal::generateLiteral(lexer.lex(st))));
-
-//     lexer.lex(st);  // (の読み飛ばし。
-
-//     s.push(t);
-//     t.add(new syntax::Tree);
-//     m = lexer.lex(st);
-//     t->push_cons(syntax::makeLexemeDatum(
-//                     literal::generateLiteral(m),
-//                     syntax::toDatumType(m)));
-
-//     lexer.lex(st);              // )の読み飛ばし
-//     // abbrevのtreeに追加する。
-//     smart_ptr<syntax::Tree> tmp = s.top(); s.pop();
-//     tmp->push_cons(t->begin());
-//     t = tmp;
-
-//     // abbrevが完了したので追加する。
-//     tmp = s.top(); s.pop();
-//     tmp->push_cons(t->begin);
-//     t = tmp;
-
-//     tmp = s.top(); s.pop();
-//     tmp->push_cons(t->begin);
-//     t = tmp;
-
-//     // 先頭はlistであるはず。
-//     asserter->check(root->begin()->first.toEnum(), syntax::DatumID::LIST);
-//     asserter->check(root->car(root->begin())->first.toEnum(),
-//                     syntax::DatumID::ABBREVIATIONS);
-//     syntax::Tree::iterator it = root->car(root->begin());
-//     ++it;
-//     asserter->check(it->first.toEnum(), syntax::DatumID::LIST);
-//     it = root->car(it);
-//     asserter->check(root->car(it)->first.toEnum(), syntax::DatumID::SYMBOL);
-//     ++it;
-//     asserter->check(root->car(it)->first.toEnum(), syntax::DatumID::NUMBER);
-
-//     return asserter->isOk();
-// }
+    utakata::lexer::Lexer lexer;
+
+    smart_ptr<lexeme::ILexeme> m(lexer.lex(st));
+    smart_ptr<syntax::Tree> root(new syntax::Tree);
+    smart_ptr<syntax::Tree> t(root);
+    std::stack<smart_ptr<syntax::Tree> > s;
+
+    // 最初から,@なので、compoundと判断し、Treeを設定する。
+    s.push(t);
+    t.add(new syntax::Tree);
+    t->push_back(syntax::makeAbbreviation(
+                     literal::generateLiteral(m)));
+
+    // (なので、再度pushして再生成。
+    lexer.lex(st);
+
+    s.push(t);
+    t.add(new syntax::Tree);
+    m = lexer.lex(st);
+    // symbol,numberをそれぞれ設定するつもりで。
+    t->push_back(syntax::makeLexemeDatum(
+                     literal::generateLiteral(m),
+                     syntax::DatumID::symbol));
+    m = lexer.lex(st);
+    t->push_back(syntax::makeLexemeDatum(
+                     literal::generateLiteral(m),
+                     syntax::DatumID::number));
+
+    // 再度abbreviation
+    s.push(t);
+    t.add(new syntax::Tree);
+    t->push_back(syntax::makeAbbreviation(
+                     literal::generateLiteral(lexer.lex(st))));
+
+    lexer.lex(st);  // (の読み飛ばし。
+
+    s.push(t);
+    t.add(new syntax::Tree);
+    m = lexer.lex(st);
+    t->push_back(syntax::makeLexemeDatum(
+                     literal::generateLiteral(m),
+                     syntax::DatumID::symbol));
+
+    lexer.lex(st);              // )の読み飛ばし
+    // abbrevのtreeに追加する。
+    smart_ptr<syntax::Tree> tmp = s.top(); s.pop();
+    tmp->push_back(t->begin(), t->end(), syntax::makeCompoundDatum(syntax::DatumID::list));
+    t = tmp;
+
+    // abbrevが完了したので追加する。
+    tmp = s.top(); s.pop();
+    tmp->push_back(t->begin(), t->end(), syntax::makeCompoundDatum(syntax::DatumID::list));
+    t = tmp;
+
+    tmp = s.top(); s.pop();
+    tmp->push_back(t->begin(), t->end(), syntax::makeCompoundDatum(syntax::DatumID::list));
+    t = tmp;
+
+    root->push_back(t->begin(), t->end(), syntax::makeCompoundDatum(syntax::DatumID::list));
+
+    // 先頭はlistであるはず。
+    asserter->check(root->begin()->first.toEnum(), syntax::DatumID::LIST, "list error");
+    syntax::Tree::iterator it = root->in_compound_begin(root->begin());
+    asserter->check(it->first.toEnum(),
+                    syntax::DatumID::ABBREVIATIONS, "abbreviation?");
+    ++it;
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST);
+    it = root->in_compound_begin(it);
+    asserter->check(it->first.toEnum(), syntax::DatumID::SYMBOL);
+    ++it;
+    asserter->check(it->first.toEnum(), syntax::DatumID::NUMBER);
+    ++it;
+    // abbrevが含まれる部分は、実際にはlistで囲まれていること。
+    asserter->check(it->first.toEnum(), syntax::DatumID::LIST);
+
+    return asserter->isOk();
+}
 
 int main(int argc, char *argv[])
 {
     simpletest::SimpleTestSuite suite("syntax tree test");
     suite.addTester(sfcr::screate(syntax_tree_test, suite.getAsserter()));
-    // suite.addTester(sfcr::screate(syntax_tree_test2, suite.getAsserter()));
+    suite.addTester(sfcr::screate(syntax_tree_test2, suite.getAsserter()));
     suite.run();
 
     return 0;
index 4b50cc1..448ce86 100755 (executable)
--- a/tree.cpp
+++ b/tree.cpp
@@ -20,13 +20,11 @@ using namespace utakata::syntax;
 
 struct Tree::TreeNode
 {
-    TreeNode (node_pair p) : car (), cdr (), stack_(), datum (p) {}
+    TreeNode (node_pair p) : list(), datum (p) {}
 
-    smart_ptr<TreeNode> car;
-    smart_ptr<TreeNode> cdr;
-
-    std::stack<smart_ptr<TreeNode> > stack_;
+    std::vector<smart_ptr<TreeNode> > list;
 
+    // datumの型と値の両方を保持する。
     Tree::node_pair datum;
 };
 
@@ -34,11 +32,7 @@ struct Tree::TreeNode
 // syntax::Tree::iterator //
 ////////////////////////////
 
-syntax::Tree::iterator::iterator () : node_()
-{
-}
-
-syntax::Tree::iterator::iterator (smart_ptr<TreeNode>& node) : node_(node)
+syntax::Tree::iterator::iterator () : current_()
 {
 }
 
@@ -56,7 +50,7 @@ syntax::Tree::iterator& syntax::Tree::iterator::operator=(const Tree::iterator&
 
 void syntax::Tree::iterator::swap (const Tree::iterator& t)
 {
-    node_ = t.node_;
+    current_ = t.current_;
 }
 
 Tree::iterator& Tree::iterator::operator++ ()
@@ -68,30 +62,20 @@ Tree::iterator& Tree::iterator::operator++ ()
     // ただし、 cdr に繋がっている cons が literal の場合、以降は進むことが
     // 無く、また list として判定されることはない。
 
-    if (node_->cdr.isNull ())
-    {
-        // 空リストは特別なものとして扱われる。
-        node_.add (new TreeNode (makeNilList ()));
-    }
-    else
-    {
-        // 原則として cdr に進むのみとする。
-        node_ = node_->cdr;
-    }
-
+    ++current_;
     return *this;
 }
 
 std::pair<DatumID, smart_ptr<literal::Literal> >& Tree::iterator::operator*()
 {
     // 現在の current_が指す node のリテラルを返す。
-    return node_->datum;
+    return (*current_)->datum;
 }
 
 std::pair<DatumID, smart_ptr<literal::Literal> >* Tree::iterator::operator->()
 {
     // 現在の current_が指す node のリテラルを返す。
-    return &(node_->datum);
+    return &((*current_)->datum);
 }
 
 bool Tree::iterator::operator==(const Tree::iterator& rh)
@@ -99,14 +83,7 @@ bool Tree::iterator::operator==(const Tree::iterator& rh)
     // node_が指す先が同一かどうかを返す。
     // 但し、自身か相手のいずれかが nil である場合だけは例外的に、単純に DatumID のみの
     // 比較になる。
-    if (rh.node_->datum.first == DatumID::nil || node_->datum.first == DatumID::nil)
-    {
-        return rh.node_->datum.first == node_->datum.first;
-    }
-    else
-    {
-        return node_ == rh.node_;
-    }
+    return current_ == rh.current_;
 }
 
 //////////////////
@@ -116,168 +93,100 @@ bool Tree::iterator::operator==(const Tree::iterator& rh)
 Tree::Tree () : node_()
 {
     // 初期値を設定する。
-    node_.add (new TreeNode (makeListDatum ()));
+    smart_ptr<TreeNode> p(new TreeNode(makeNilList()));
+    // 最後尾には常にnilがいることにする。
+    node_.push_back(p);
 }
 
 Tree::iterator Tree::begin ()
 {
     // 開始点を示すデータを返す。
-    return iterator (node_);
+    iterator it;
+    it.current_ = node_.begin();
+    return it;
 }
 
 Tree::iterator Tree::end ()
 {
     // 終了地点を示す部分を返す。
-    // stack が無く、 nil であるものを指す。
-    smart_ptr<TreeNode> n (new TreeNode (makeNilList ()));
-    return iterator (n);
+    iterator it;
+    it.current_ = node_.end();
+    return it;
 }
 
-Tree::iterator Tree::cons_(iterator it, smart_ptr<TreeNode> car)
+void Tree::push_back(node_pair datum)
 {
-    // 渡された smart_ptr を car に設定する。
-    // it.node_が null の場合には生成し、生成した car に設定する。
+    // 渡されたdatumを、現在保持しているデータ型に追加する。
+    // 末尾には常にnilがいるので、その一つ前に設定することにする。
+    smart_ptr<TreeNode> p(new TreeNode(datum));
+    node_.insert(--(node_.end()), p);
+}
 
-    std::cout << "make cons " << (car->datum.second.isNull() ? "nil" : car->datum.second->toValue()->toStr()) << " ";
-    std::cout << car->datum.first.toEnum() << std::endl;
-    
-    if (it.node_.isNull ())
-    {
-        it.node_.add (new TreeNode (makeListDatum ()));
-        it.node_->car = car;
+void Tree::push_back(Tree::iterator it, Tree::iterator it2,
+                     node_pair datum)
+{
+    // itとit2までを、datumで設定されたdatumidであるcompound datum
+    // に格納して追加する。
+    smart_ptr<TreeNode> p(new TreeNode(datum));
+    p->list.insert(p->list.end(), it.current_, it2.current_);
+    node_.insert(--(node_.end()), p);
+}
 
-        return it;
+Tree::iterator Tree::in_compound_begin(Tree::iterator it)
+{
+    // itがcompound datumである場合に、compound datumの内部リストを返す。
+    if (isCompoundDatum(it))
+    {
+        iterator ret;
+        ret.current_ = (*it.current_)->list.begin();
+        return ret;
     }
     else
     {
-        if (it.node_->car.isNull ())
-        {
-            // it が指している node_.car が完全にどこも指していない場合、
-            // ここに設定してやる。
-            it.node_->car.add (new TreeNode(makeListDatum ()));
-            it.node_->car = car;
-            return it;
-        }
-        else
-        {
-            smart_ptr<TreeNode> n (new TreeNode (makeListDatum ()));
-            n->car = car;
-
-            // cdr に直接設定する。
-            it.node_->cdr = n;
-            // 返されるイテレータは、あくまで追加したものを指すイテレータが返
-            // される。
-
-            return iterator (n);
-        }
+        // 違う場合には、endを返すことにする。
+        return end();
     }
 }
 
-Tree::iterator Tree::cons_(iterator it, smart_ptr<TreeNode> car,
-                           smart_ptr<TreeNode> cdr)
+Tree::iterator Tree::in_compound_end(Tree::iterator it)
 {
-    // 渡された it の car と cdr にそれぞれ設定する。
-    // it.node_が存在していない場合には、生成後に car と cdr をそれぞれ
-    // 設定する。
-    if (it.node_.isNull ())
+    // itがcompound datumである場合に、compound datumの内部リストを返す。
+    if (isCompoundDatum(it))
     {
-        it.node_.add (new TreeNode (makeListDatum ()));
-        it.node_->car = car;
-        it.node_->cdr = cdr;
-
-        return it;
+        iterator ret;
+        ret.current_ = (*it.current_)->list.end();
+        return ret;
     }
     else
     {
-        if (it.node_->car.isNull ())
-        {
-            // it が指している node_.car が完全にどこも指していない場合、
-            // ここに設定してやる。
-            it.node_->car.add (new TreeNode(makeListDatum ()));
-            it.node_->car = car;
-            it.node_->cdr = cdr;
-            return it;
-        }
-        else
-        {
-            smart_ptr<TreeNode> n (new TreeNode (makeListDatum ()));
-            n->car = car;
-            n->cdr = cdr;
-
-            // cdr に直接設定する。
-            it.node_->cdr = n;
-            // 返されるイテレータは、あくまで追加したものを指すイテレータが返
-            // される。
-
-            return iterator (n);
-        }
+        // 違う場合には、endを返すことにする。
+        return end();
     }
 }
 
-
-Tree::iterator Tree::cons (iterator it, Tree::node_pair p)
-{
-    // car が p,cdr が nil である treenode を it の cdr に設定する。
-
-    // 追加して、結果を返す。
-
-    smart_ptr<TreeNode> n (new TreeNode (p));
-    return cons_(it, n);
-}
-
-Tree::iterator Tree::cons (iterator it, iterator car)
-{
-    // car が p,cdr が nil である treenode を it の cdr に設定する。
-
-    return cons_(it, car.node_);
-}
-
-Tree::iterator Tree::cons (iterator it, Tree::node_pair car, Tree::node_pair cdr)
-{
-    // car と cdr がそれぞれ設定された対を、 it の cdr に設定する。
-    smart_ptr<TreeNode> a1 (new TreeNode (car));
-    smart_ptr<TreeNode> a2 (new TreeNode (cdr));
-    return cons_(it, a1, a2);
-}
-
-Tree::iterator Tree::cons (iterator it, iterator car, iterator cdr)
-{
-    return cons_(it, car.node_, cdr.node_);
-}
-
-Tree::iterator Tree::cons (iterator it, iterator car, Tree::node_pair cdr)
-{
-    smart_ptr<TreeNode> a(new TreeNode(cdr));
-    return cons_(it, car.node_, a);
-}
-
-Tree::iterator Tree::cons (iterator it, Tree::node_pair car, iterator cdr)
-{
-    smart_ptr<TreeNode> a(new TreeNode(car));
-    return cons_(it, a, cdr.node_);
-}
-
-Tree::iterator syntax::Tree::car (iterator it)
-{
-    // 渡された it の car を iterator として返す。
-    return iterator (it.node_->car);
-}
-
-Tree::iterator syntax::Tree::cdr (iterator it)
-{
-    // 渡された it の cdr を iterator として返す。
-    return iterator (it.node_->cdr);
-}
-
 //////////////////////
 // helper functions //
 //////////////////////
 
-std::pair<DatumID, smart_ptr<literal::Literal> > syntax::makeListDatum ()
+bool syntax::isCompoundDatum(Tree::iterator it)
+{
+    if (it->first == syntax::DatumID::list ||
+        it->first == syntax::DatumID::vector ||
+        it->first == syntax::DatumID::byteVector)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+std::pair<DatumID, smart_ptr<literal::Literal> > syntax::makeCompoundDatum (
+    DatumID id)
 {
     // datum_id が list である node_pair を返す。
-    return std::pair<DatumID, smart_ptr<literal::Literal> >(
-        DatumID (DatumID::list), smart_ptr<literal::Literal>());
+    return std::pair<DatumID, smart_ptr<literal::Literal> >(id, smart_ptr<literal::Literal>());
 }
 
 std::pair<DatumID, smart_ptr<literal::Literal> > syntax::makeNilList ()
diff --git a/tree.h b/tree.h
index 14743a4..ce2263a 100755 (executable)
--- a/tree.h
+++ b/tree.h
@@ -58,7 +58,6 @@ namespace utakata {
             public:
                 // ツリーを巡回し、そのノードの literal を取得することを可能とする。
                 iterator ();
-                iterator (smart_ptr<TreeNode>& node);
                 iterator (const iterator& s);
                 
                 ~iterator () {}
@@ -71,10 +70,11 @@ namespace utakata {
                 // 一致するかどうかを返す
                 bool operator==(const iterator& rh);
                 bool operator!=(const iterator& rh) {
-                    return ! (node_ == rh.node_);
+                    return ! (*this == rh);
                 }
 
-                smart_ptr<TreeNode> node_;
+                // 現在位置を表すiterator
+                std::vector<smart_ptr<TreeNode> >::iterator current_;
 
             private:
 
@@ -93,42 +93,32 @@ namespace utakata {
             iterator begin ();
             iterator end ();
 
-            // insert 、 append ともに cons のみでどうにかする。
+            // push_backによって追加を行う。
+            void push_back (node_pair datum);
+            void push_back (iterator b, iterator e, node_pair datum);
 
-            // it の cdr に、 node_pair が car である TreeNode を設定する。
-            // it1 の car に、 it2 の node_を設定する。
-            // それぞれのパターンをオーバーロードしておくことで、十分な柔軟性が出せる。
-            
-            iterator push_back (iterator it, node_pair car);
-            iterator push_back (iterator it, iterator it2);
-            iterator push_back (iterator it, node_pair car, node_pair cdr);
-            iterator push_back (iterator it, node_pair car, iterator cdr);
-            iterator push_back (iterator it, iterator car, node_pair cdr);
-            iterator push_back (iterator it, iterator car, iterator cdr);
+            // itが指すnodeの内部listの先頭を返す。
+            iterator in_compound_begin(iterator it);
+            iterator in_compound_end(iterator it);
 
-            // 渡した iterator の car/cdr をそれぞれ取得する。
-            iterator car (iterator it);
-            iterator cdr (iterator it);
+            size_t size() const {return node_.size();}
 
         private:
 
-            iterator cons_(iterator it, smart_ptr<TreeNode> n);
-            iterator cons_(iterator it, smart_ptr<TreeNode> car, smart_ptr<TreeNode> cdr);
-
-        private:
-
-            smart_ptr<TreeNode> node_;
+            std::vector<smart_ptr<TreeNode> > node_;
 
         };
 
         // 渡した iterator が list datum であるかどうかを返す。
-        bool isList (Tree::iterator node);
+        bool isCompoundDatum (Tree::iterator node);
 
         // 渡した node が literal であるかどうかを返す。
         bool isLiteral (Tree::iterator node);
 
         // 各 datum を表す std::pair を作成するためのヘルパ関数。
-        std::pair<DatumID, smart_ptr<literal::Literal> > makeListDatum ();
+        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);
diff --git a/tree_impl.h b/tree_impl.h
deleted file mode 100644 (file)
index fa16de8..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _TREE_IMPL_H_
-#define _TREE_IMPL_H_
-
-#include "tree.h"
-#include "smart_ptr.h"
-
-namespace utakata {
-
-    namespace utf8_string {
-        class UTF8String;
-    };
-
-    namespace literal {
-        class LiteralData;
-    };
-    
-    namespace syntax {
-    
-        class LiteralTree : public Tree
-        {
-            // 各lexeme datumを保持するためのツリー実装。
-            // ツリーとしては、
-        public:
-
-            LiteralTree(const DatumID id, smart_ptr<literal::LiteralData> dat);
-            virtual ~LiteralTree() {}
-
-        private:
-
-            void setCar_(smart_ptr<Tree> tree);
-            void setCdr_(smart_ptr<Tree> tree) {}
-
-            smart_ptr<Tree> car_() const;
-            smart_ptr<Tree> cdr_() const;
-
-            smart_ptr<utf8_string::UTF8String> value_() const;
-
-            smart_ptr<literal::LiteralData> literal_();
-
-        private:
-
-            smart_ptr<Tree> literal_;
-            smart_ptr<literal::LiteralData> data_;
-        };
-    
-    };
-
-};
-
-#endif /* _TREE_IMPL_H_ */