#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
+++ /dev/null
-#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);
-}
+++ /dev/null
-#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_ */
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;
}
}
-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;
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;
// 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;
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;
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;
}
};
- class ListHandler : public IParserHandler
+ // <list>に対応するものだけは、carとcdrでハンドラが分離している。
+ class ListCarHandler : public IParserHandler
{
// PS_LIST_CARである間に対応するハンドラ
public:
- ListHandler() {}
- virtual ~ListHandler() {}
+ ListCarHandler() {}
+ virtual ~ListCarHandler() {}
private:
};
+
+ class ListCdrHandler : public IParserHandler
+ {
+ // PS_LIST_CDRである間に対応するハンドラ
+ public:
+ ListCdrHandler() {}
+ virtual ~ListCdrHandler() {}
+
+ private:
+
+ bool exec_(HandlerData& data);
+
+ };
+
+
class DotHandler : public IParserHandler
{
// PS_AFTER_DOTに対応するハンドラ
};
+ // <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に対応するハンドラ
};
+ class ErrorHandler : public IParserHandler
+ {
+ // PS_ERRORをハンドリングする。実際にはエラーを通告する
+ // のみ。
+ public:
+ ErrorHandler() {}
+ virtual ~ErrorHandler() {}
+
+ private:
+
+ bool exec_(HandlerData& data);
+
+ };
+
};
};
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;
};
PS_VECTOR_END = 16, /* #(と対応した) */
PS_BYTEVECTOR_START = 17, /* #vu8( */
PS_BYTEVECTOR_END = 18, /* #vu8(と対応した) */
+ PS_ERROR, // 構文異常が発生した場合に設定される。
+ // これが設定されている場合、lexmの読み出しは進まず、
+ // その時点で終了することになる。
+ PS_END_DOT, // listの終了時点を表す。)以外は許容されない。
};
};
};
using namespace std;
using namespace utakata;
+
+
bool parser_test(smart_ptr<simpletest::SimpleTestAsserter> asserter)
{
std::stringstream ss;
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));
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;
}
// 他の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();
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");
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;
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;
};
// syntax::Tree::iterator //
////////////////////////////
-syntax::Tree::iterator::iterator () : node_()
-{
-}
-
-syntax::Tree::iterator::iterator (smart_ptr<TreeNode>& node) : node_(node)
+syntax::Tree::iterator::iterator () : current_()
{
}
void syntax::Tree::iterator::swap (const Tree::iterator& t)
{
- node_ = t.node_;
+ current_ = t.current_;
}
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)
// 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_;
}
//////////////////
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 ()
public:
// ツリーを巡回し、そのノードの literal を取得することを可能とする。
iterator ();
- iterator (smart_ptr<TreeNode>& node);
iterator (const iterator& s);
~iterator () {}
// 一致するかどうかを返す
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:
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);
+++ /dev/null
-#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_ */