00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "precomp.h"
00010 #include "API/Core/System/clanstring.h"
00011 #include "API/Core/System/error.h"
00012 #include "component_tokenizer.h"
00013
00014 CL_ComponentTokenizer::CL_ComponentTokenizer(const std::string &_data, const std::string &_filename)
00015 {
00016 filename = _filename;
00017 string_data = _data;
00018 data = (char *) string_data.c_str();
00019 total_size = string_data.size();
00020
00021 peek_pos = 0;
00022 last_line = 0;
00023 in_remark = false;
00024 tokenize();
00025 }
00026
00027 CL_ComponentTokenizer::~CL_ComponentTokenizer()
00028 {
00029 }
00030
00031 bool CL_ComponentTokenizer::is_operator(char c)
00032 {
00033 return
00034 c == ',' ||
00035 c == '=' ||
00036 c == '(' ||
00037 c == ')' ||
00038 c == ';' ||
00039 c == '{' ||
00040 c == '}' ||
00041 c == '<' ||
00042 c == '+' ||
00043 c == '-' ||
00044 c == '*' ||
00045 c == '/' ||
00046 c == '>';
00047 }
00048
00049 bool CL_ComponentTokenizer::is_space(char c)
00050 {
00051 return
00052 c == ' ' ||
00053 c == '\t' ||
00054 c == 13 ||
00055 c == 10;
00056 }
00057
00058 bool CL_ComponentTokenizer::is_remark(char c, int position)
00059 {
00060 if (in_remark)
00061 {
00062 if (c == '\n')
00063 {
00064 in_remark = false;
00065 }
00066 return true;
00067 }
00068 else
00069 {
00070 if (c == '/')
00071 {
00072 if (
00073 position+1 < total_size &&
00074 data[position+1] == '/')
00075 {
00076 in_remark = true;
00077 return true;
00078 }
00079 }
00080 else if (c == '#')
00081 {
00082 in_remark = true;
00083 return true;
00084 }
00085 }
00086 return false;
00087 }
00088
00089 void CL_ComponentTokenizer::tokenize()
00090 {
00091 int cur_pos = 0;
00092 int cur_line = 0;
00093 while (cur_pos < total_size)
00094 {
00095 while (
00096 cur_pos < total_size &&
00097 (
00098 is_remark(data[cur_pos], cur_pos) ||
00099 is_space(data[cur_pos])
00100 ))
00101 {
00102 if (data[cur_pos] == '\n') cur_line++;
00103 cur_pos++;
00104 }
00105 if (cur_pos == total_size) break;
00106
00107 if (is_operator(data[cur_pos]))
00108 {
00109 tokens.push_back(CL_Token(std::string(&data[cur_pos], 1), cur_pos, cur_line));
00110 cur_pos++;
00111 }
00112 else
00113 {
00114 int temp_pos = cur_pos;
00115 if (data[temp_pos] == '"')
00116 {
00117 int num_chars = 0;
00118 temp_pos++;
00119 while (temp_pos < total_size)
00120 {
00121 if (data[temp_pos] == '"')
00122 {
00123 if (temp_pos+1>=total_size || data[temp_pos+1] != '"') break;
00124 else
00125 {
00126 temp_pos++;
00127 }
00128 }
00129 temp_pos++;
00130 num_chars++;
00131 }
00132 if (temp_pos == total_size)
00133 {
00134 write_error("Missing '""' following '""'-begin");
00135 break;
00136 }
00137
00138 char *temp = new char[num_chars+1];
00139 temp[num_chars] = 0;
00140 int ofs = 1;
00141 for (int i=0;i<num_chars;i++)
00142 {
00143 temp[i] = data[cur_pos+ofs+i];
00144 if (data[cur_pos+ofs+i] == '"')
00145 {
00146 ofs++;
00147 }
00148 }
00149 cur_pos = temp_pos+1;
00150
00151 tokens.push_back(CL_Token(std::string(temp), cur_pos, cur_line));
00152 delete temp;
00153 }
00154 else
00155 {
00156 while (temp_pos < total_size &&
00157 !is_space(data[temp_pos]) &&
00158 !is_operator(data[temp_pos]) &&
00159 !is_remark(data[temp_pos], cur_pos))
00160 {
00161 temp_pos++;
00162 }
00163 int tok_size = temp_pos-cur_pos;
00164 tokens.push_back(CL_Token(std::string(&data[cur_pos], tok_size), cur_pos, cur_line));
00165 cur_pos += tok_size;
00166 }
00167 }
00168 }
00169 }
00170
00171 std::string CL_ComponentTokenizer::get_next_token(int *offset)
00172 {
00173 peek_pos = 0;
00174 last_line = tokens[0].line;
00175 std::string token = tokens[0].token;
00176 if (offset != NULL) *offset = tokens[0].offset;
00177
00178 tokens.pop_front();
00179
00180 return token;
00181 }
00182
00183 std::string CL_ComponentTokenizer::peek_next_token(int *offset)
00184 {
00185 if (peek_pos >= (int) tokens.size())
00186 {
00187 return "";
00188 }
00189 if (offset != NULL) *offset = tokens[peek_pos].offset;
00190 return tokens[peek_pos++].token;
00191 }
00192
00193 void CL_ComponentTokenizer::pop_to_peek()
00194 {
00195 while (peek_pos > 0)
00196 {
00197 peek_pos--;
00198 tokens.pop_front();
00199 }
00200 }
00201
00202 std::string CL_ComponentTokenizer::write_error(std::string err_msg)
00203 {
00204 CL_String err;
00205 err << "Error occured during read of config file '" <<
00206 filename.c_str() << "' (line " << last_line << "): " << err_msg.c_str();
00207
00208 return err;
00209 }