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