1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
//
// Zinnia: Online hand recognition system with machine learning
//
// $Id: sexp.cpp 17 2009-04-05 11:40:32Z taku-ku $;
//
// Copyright(C) 2008 Taku Kudo <taku@chasen.org>
//
#include <iostream>
#include <string>
#include "sexp.h"
namespace zinnia {
namespace {
void dump_cdr_internal(const Sexp::Cell *cell,
std::ostream *os);
void dump_internal(const Sexp::Cell *cell,
std::ostream *os) {
if (!cell) {
*os << "NIL";
} else {
if (cell->is_cons()) {
*os << '(';
dump_internal(cell->car(), os);
dump_cdr_internal(cell->cdr(), os);
*os << ')';
} else if (cell->is_atom()) {
*os << cell->atom();
}
}
}
void dump_cdr_internal(const Sexp::Cell *cell,
std::ostream *os) {
if (!cell) {
return;
}
if (cell->is_cons()) {
*os << ' ';
dump_internal(cell->car(), os);
dump_cdr_internal(cell->cdr(), os);
} else {
*os << ' ';
dump_internal(cell, os);
}
}
}
const Sexp::Cell *Sexp::read(char **begin, const char *end) {
comment(begin, end);
if (*begin >= end) {
return 0;
}
const int r = next_token(begin, end, '(');
if (r == 1) {
return read_car(begin, end);
} else if (r == 0) {
return read_atom(begin, end);
}
return 0;
}
void Sexp::dump(const Sexp::Cell *cell, std::ostream *os) {
dump_internal(cell, os);
*os << std::endl;
}
void Sexp::free() {
cell_freelist_.free();
char_freelist_.free();
}
int Sexp::next_token(char **begin, const char *end, const char n) {
char c = 0;
do {
c = **begin;
++(*begin);
} while (isspace(c));
if (*begin >= end) {
return -1;
}
if (c == n) {
return 1;
} else {
--(*begin);
return 0;
}
}
void Sexp::comment(char **begin, const char *end) {
const int r = next_token(begin, end, ';');
if (r == 1) {
while (*begin < end) {
const char c = **begin;
++(*begin);
if (c == '\r' || c == '\n') {
break;
}
}
return comment(begin, end);
}
}
const Sexp::Cell *Sexp::read_cdr(char **begin, const char *end) {
comment(begin, end);
const int r = next_token(begin, end, ')');
if (r == 1) {
return 0;
} else if (r == 0) {
return read_car(begin, end);
}
return 0;
}
const Sexp::Cell *Sexp::read_car(char **begin, const char *end) {
comment(begin, end);
const int r = next_token(begin, end, ')');
if (r == 1) {
return 0;
} else if (r == 0) {
Cell *cell = cell_freelist_.alloc(1);
cell->set_car(this->read(begin, end));
cell->set_cdr(read_cdr(begin, end));
return cell;
}
return 0;
}
const Sexp::Cell *Sexp::read_atom(char **begin, const char *end) {
comment(begin, end);
char c = **begin;
const char *p = *begin;
++(*begin);
if (isspace(c) || c == '(' || c == ')') {
return 0;
} else if (*begin >= end) {
return 0;
} else {
while (true) {
c = **begin;
++(*begin);
if (isspace(c) || c == '(' || c == ')' || *begin >= end) {
--(*begin);
const size_t length = static_cast<size_t>(*begin - p);
char *tmp = char_freelist_.alloc(length + 1);
std::copy(p, p + length, tmp);
tmp[length] = '\0';
Cell *cell = cell_freelist_.alloc(1);
cell->set_atom(tmp);
return cell;
}
}
}
return 0;
}
}
|