source: anotherchoice/tags/jsp-1.4.4-full-UTF8/cfg/base/parser.cpp@ 26

Last change on this file since 26 was 26, checked in by ykominami, 12 years ago

initial

File size: 43.1 KB
Line 
1/*
2 * TOPPERS/JSP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
5 *
6 * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 *
9 * 上記著作権者
10は,以下の (1)〜(4) の条件か,Free Software Foundation
11 * によってå…
12¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
13 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
14 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
16 * 利用と呼ぶ)することを無償で許諾する.
17 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
18 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
19 * スコード中に含まれていること.
20 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
21 * 用できる形で再é…
22å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
23å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
24 * 者
25マニュアルなど)に,上記の著作権表示,この利用条件および下記
26 * の無保証規定を掲載すること.
27 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
28 * 用できない形で再é…
29å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
30 * と.
31 * (a) 再é…
32å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
33マニュアルなど)に,上記の著
34 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
35 * (b) 再é…
36å¸ƒã®å½¢æ…
37‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
38 * 報告すること.
39 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 * 害からも,上記著作権者
41およびTOPPERSプロジェクトをå…
42è²¬ã™ã‚‹ã“と.
43 *
44 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
45お
46 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
47 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
48 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
49 *
50 * @(#) $Id: parser.cpp,v 1.18 2003/12/15 07:32:14 takayuki Exp $
51 */
52
53
54
55// $Header: /home/CVS/configurator/base/parser.cpp,v 1.18 2003/12/15 07:32:14 takayuki Exp $
56
57#include "base/defs.h"
58#include "base/parser.h"
59#include <sstream>
60#include <set>
61#include <map>
62#include <iomanip>
63
64using namespace std;
65
66/*
67 * å…
68ˆé ­ã¨æœ«å°¾ã«ã‚る空白文字を取り除く
69 */
70Token & Token::trim(void)
71{
72 string::iterator scope;
73
74 /* あたま */
75 scope = begin();
76 while(*scope == ' ' || *scope == '\t' || *scope == '\r' || *scope == '\n')
77 ++ scope;
78 erase(begin(), scope);
79
80 if(!empty())
81 {
82 /* おしり */
83 scope = end();
84 do {
85 -- scope;
86 } while(*scope == ' ' || *scope == '\t' || *scope == '\r' || *scope == '\n');
87 ++ scope;
88 erase(scope, end());
89 }
90 return *this;
91}
92
93
94 /*
95 * 文字列リテラルの展開 (ダブルクォートの取り除き + エスケープシーケンスの展開)
96 */
97Token & Token::chopLiteral(void)
98{
99 if(type != STRINGLITERAL)
100 return *this;
101
102 string::iterator scope;
103
104 //エラー処理のために非破壊処理をする
105 string src(*this);
106 string work;
107
108 if(src[0] != '"' || src[src.length()-1] != '"')
109 return *this;
110
111 src = src.substr(1, src.length()-2);
112
113 scope = src.begin();
114 while(scope != src.end())
115 {
116 if(*scope == '\\')
117 {
118 //リテラルの末尾が\で終わることはないのでチェックしない
119 ++ scope;
120 switch(*scope)
121 {
122 case '"': work += '"'; break;
123 case 't': work += '\t'; break;
124 case 'r': work += '\r'; break;
125 case 'n': work += '\n'; break;
126 case 'b': work += '\b'; break;
127 case '\\': work += '\\'; break;
128 default:
129 ExceptionMessage("Illegal escape sequence [\\%]","エスケープシーケンス[\\%]は不正です") << *scope << throwException;
130 }
131 }else
132 work += *scope;
133
134 ++ scope;
135 }
136
137 type = STRING;
138 assign(work);
139 value = this->length();
140
141 return *this;
142}
143
144 /* 区切り文字 (一文字だけで意味を成す文字) */
145const char * Parser::Punctuator =
146 ",;(){}";
147
148 /* 演算子 (特殊文字からなる文字) */
149const char * Parser::Operator =
150 "+-*/&|%^~!?[]=:.#";
151
152Token Parser::lastErrorToken;
153
154
155 /*
156 * ストリームから一文字だけ切り出す
157 */
158inline int Parser::getChar(void)
159{
160 int work = current->stream->get();
161
162 /* 行番号の処理 */
163 if(work == '\n')
164 current->line ++;
165
166 /* ストリームログのための処理 */
167 if(PutBackCount == 0)
168 {
169 if(LogBuffer != 0 && isenabled(LOGGING))
170 *LogBuffer += static_cast<char>(work);
171 }else
172 PutBackCount --; //すでに読み込んでいる
173
174 return work;
175}
176
177 /*
178 * 取り出しすぎた文字をストリームに返す
179 */
180inline void Parser::putBack(int ch)
181{
182 /* 行番号のための処理 */
183 if(ch == '\n')
184 current->line --;
185
186 /* ストリームログのための処理 */
187 PutBackCount ++;
188
189 current->stream->putback(ch);
190}
191
192 /*
193 * Parserクラスのデストラクタ
194 */
195Parser::~Parser(void)
196{
197 list<tagFile *>::iterator scope;
198
199 /* 最後までパースしてないなら、とりあえずスタックにå…
200¥ã‚Œã¦ãŠã */
201 if(current != 0)
202 fileStack.push_front(current);
203
204 /* スタックの中身å…
205¨éƒ¨ã‚’破棄 */
206 scope = fileStack.begin();
207 while(scope != fileStack.end())
208 {
209 if((*scope)->stream != 0 && (*scope)->stream != &cin)
210 delete (*scope)->stream; //ストリームの破棄
211 delete (*scope); //構造体のデータ領域の破棄
212
213 ++ scope;
214 }
215
216 /* 念のため */
217 fileStack.clear();
218 TokenStack.clear();
219}
220
221
222 /*
223 * 識別子の切出し (識別子 = [a-zA-Z_][0-9a-zA-Z_]*)
224 */
225bool Parser::getIdentifier(Token & token,int ch)
226{
227 token.value = 0;
228
229 do {
230 token.value ++;
231 token += static_cast<char>(ch);
232 ch = getChar();
233 } while( (ch >='a' && ch <= 'z') || (ch >='A' && ch <= 'Z') || (ch == '_') || (ch >= '0' && ch <= '9') );
234
235 if(ch != -1)
236 putBack(static_cast<char>(ch));
237
238 token.type = Token::IDENTIFIER;
239 return true;
240}
241
242
243 /*
244 * ディレクティブの切出しと処理
245 */
246bool Parser::parseDirectives(Token & token, int ch, bool allow_space)
247{
248 Token directive;
249 map<string, ParseUnit *>::iterator scope;
250
251 //空白読み飛ばし
252 do {
253 token += static_cast<char>(ch);
254 ch = getChar();
255 } while(ch == ' ' || ch == '\t');
256
257 if(ch >= '0' && ch <= '9')
258 {
259 //GNU-cpp lineディレクティブ 対策
260 directive.assign("line");
261 this->putBack(ch);
262 }else
263 {
264 //ディレクティブの読み出し
265 putBack(ch);
266 getToken(directive);
267 token += directive;
268 }
269
270 //lineディレクティブの解析
271 if(directive.compare("line") == 0)
272 {
273 Token token;
274
275 getToken(token, Token::INTEGER);
276 setCurrentLine(token.value -1);
277
278 getToken(token, Token::STRINGLITERAL);
279 try {
280 token.chopLiteral();
281 }
282 catch(Exception &) {
283 token.assign("Unknown");
284 }
285 setStreamIdentifier(token);
286
287 return true;
288 }
289
290 //pragmaディレクティブの解析
291 if(directive.compare("pragma") == 0)
292 {
293 getToken(directive);
294 token += " ";
295 token += directive;
296
297 if((scope = Directive::container().find(directive)) != Directive::container().end())
298 {
299 (*scope).second->body(directive, *Container, *this, string(""));
300
301 //余分なトークンの読み飛ばし
302 if(!TokenStack.empty())
303 {
304 do {
305 token = TokenStack.front();
306 TokenStack.pop_front();
307 } while(!TokenStack.empty() && !allow_space && token.type == Token::SPACE);
308
309 return true;
310 }
311 }
312 }
313
314 //includeディレクティブの解析
315 if(directive.compare("include") == 0)
316 {
317 cerr << getStreamLocation() << Message(": Configurator found 'include' directive\nKernel configuration file must be preprocessed.\n",": #includeディレクティブを発見しました\n カーネル構成ファイルはCプリプロセッサを通過させる必
318要があります\n");
319 ExceptionMessage("Illegal kernel configuration file","不正なカーネル構成ファイル").throwException();
320 }
321
322 putBack(directive);
323 return false;
324}
325
326
327 /*
328 * 空白文字の切出し
329 * ・スペース, タブ ・#で始まって改行まで ・C言語のコメントブロック
330 * ・2連のスラッシュ(//)から改行まで
331 * ・上の4つを組み合わせたもの
332 */
333bool Parser::getWhitespace(Token & token, int ch, bool allow_space)
334{
335 int prev;
336
337 token.type = Token::SPACE;
338 switch(ch)
339 {
340 case '/':
341 ch = getChar();
342
343 switch(ch)
344 {
345 /* コメントブロック */
346 case '*':
347 token += "/*";
348 prev = '\x0';
349 while( ((ch = getChar()) != '/') || (prev!='*'))
350 {
351 token += static_cast<char>(ch);
352 prev = ch;
353 }
354 token += static_cast<char>(ch);
355 break;
356
357 /* ダブルスラッシュ */
358 case '/':
359 token += '/';
360 do {
361 token += static_cast<char>(ch);
362 } while( (ch = getChar()) != '\n' );
363 break;
364
365 /* ただ'/'で始まっただけでした */
366 default:
367 putBack(ch);
368 return getOperator(token, '/');;
369 }
370 break;
371
372 /* # で始まる行 */
373 case '#':
374 /* ディレクティブが無効 or そんなディレクティブは知らない */
375 if(! (isenabled(DIRECTIVE) && parseDirectives(token, ch, allow_space)) )
376 {
377 //改行まで読み飛ばし
378 TokenStack.clear();
379 do {
380 token += static_cast<char>(ch);
381 ch = getChar();
382 } while(ch != '\n');
383 putBack(ch);
384 }
385 break;
386
387 /* 俗に言う空白文字 */
388 case ' ':
389 case '\t':
390 case '\n':
391 case '\r':
392 do {
393 token += static_cast<char>(ch);
394 ch = getChar();
395 } while((ch == ' ') || (ch == '\n') || (ch == '\r') || (ch == '\t'));
396 putBack(static_cast<char>(ch));
397 break;
398 }
399 return true;
400}
401
402 /*
403 * 整数値の切出し (8/10/16進, 正数/負数)
404 * ・2進は不評だったのでやめました
405 */
406bool Parser::getInteger(Token & token, int ch)
407{
408 bool minus = false;
409
410 if(ch == '-')
411 {
412 minus = true;
413 ch = getChar();
414 if(ch < '0' || ch >'9')
415 {
416 putBack(static_cast<char>(ch));
417 return false;
418 }
419 token += "-";
420 }
421
422 token.type = Token::INTEGER;
423 token.value = 0;
424
425 if(ch == '0')
426 {
427 token += static_cast<char>(ch);
428 ch = getChar();
429 if(ch == 'x' || ch == 'X')
430 {
431 token += static_cast<char>(ch);
432 ch = getChar();
433 while((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
434 {
435 token += static_cast<char>(ch);
436 if((ch -= '0') >= 10)
437 {
438 ch = ch + '0' - 'A' + 10;
439 if(ch >= 16)
440 ch = ch - ('a' - 'A');
441 }
442 token.value = token.value * 16 + ch;
443 ch = getChar();
444 }
445 }else
446 {
447 while(ch >= '0' && ch <= '7')
448 {
449 token += static_cast<char>(ch);
450 token.value = token.value * 8 + ch - '0';
451 ch = getChar();
452 }
453 }
454 }else
455 {
456 do {
457 token += static_cast<char>(ch);
458 token.value = token.value * 10 + ch - '0';
459 ch = getChar();
460 } while(ch >= '0' && ch <= '9');
461 }
462
463 /* integer-suffix */
464 if(ch != -1)
465 {
466 bool unsigned_suffix = false;
467 bool long_suffix = false;
468
469 int first_longsuffix;
470
471 if(ch == 'u' || ch == 'U')
472 {
473 unsigned_suffix = true;
474 token += static_cast<char>(ch);
475 ch = getChar();
476 }
477
478 if(ch == 'i' || ch == 'I') //i8, i16, i32, i64
479 {
480 int first, second;
481 bool accept = false;
482 const signed char suffix_list[10] = { -1, '6', -1, '2', -1, -1, '4', -1, 0, -1}; //8, 16, 32, 64のみを受理
483
484 first = getChar();
485 second = -1;
486 if(first >= '0' && first <= '9')
487 {
488 if(suffix_list[first - '0'] > 0)
489 {
490 second = getChar();
491 if(second == suffix_list[first - '0'])
492 accept = true;
493 }else
494 if(suffix_list[first - '0'] == 0)
495 accept = true;
496 }
497
498 if(!accept)
499 {
500 if(second != -1)
501 putBack(second);
502 putBack(first);
503 } else
504 {
505 token += static_cast<char>(ch);
506 token += static_cast<char>(first);
507 if(second != -1)
508 token += static_cast<char>(second);
509 ch = getChar();
510 }
511 } else
512 {
513 if(ch == 'l' || ch == 'L')
514 {
515 first_longsuffix = ch;
516 long_suffix = true;
517
518 token += static_cast<char>(ch);
519 ch = getChar();
520 if(ch == first_longsuffix)
521 {
522 token += static_cast<char>(ch);
523 ch = getChar();
524 }
525 }
526
527 if(!unsigned_suffix && (ch == 'u' || ch == 'U'))
528 {
529 token += static_cast<char>(ch);
530 ch = getChar();
531 }
532 }
533 }
534
535 if(minus)
536 token.value = - token.value;
537
538 if(ch != -1)
539 putBack(static_cast<char>(ch));
540
541 return true;
542}
543
544
545 /*
546 * オペレータ(特殊文字の組合せからなるトークン)の切出し
547 */
548bool Parser::getOperator(Token & token, int ch)
549{
550 const char * work;
551
552 /* chがオペレータ文字であるかどうか確かめる */
553 for(work = Operator;*work != '\x0' && *work != ch;work++);
554 if(*work == '\x0')
555 return false;
556
557 /* 後続する文字もオペレータ文字であるかどうか確かめる */
558 do {
559 token += static_cast<char>(ch);
560 ch = getChar();
561 for(work = Operator;*work != '\x0' && *work != ch;work++);
562 } while(*work != '\x0');
563
564 putBack(ch);
565 token.type = Token::OPERATOR;
566 return true;
567}
568
569
570 /*
571 * 文字列リテラル (ダブルクォートで括られた文字)
572 * ・シングルクォートも許すようにした
573 *
574 * VisualStudio6.0でコンパイルした場合、改行がLFのファイルに対してtellg後に
575 * getするとEOFが返るため、同処理をコメントアウトしておく。
576 */
577bool Parser::getStringLiteral(Token & token, int delimitor)
578{
579 int ch;
580 int prev;
581
582 ch = delimitor;
583
584 token.value = 1;
585 token.type = Token::STRINGLITERAL;
586 token.assign("");
587 token += static_cast<char>(ch);
588
589 while(!current->stream->bad() && !current->stream->eof())
590 {
591 prev = ch;
592 ch = getChar();
593 token += static_cast<char>(ch);
594 token.value ++;
595
596 if(ch == delimitor && prev != '\\')
597 return true;
598 }
599
600 //いったん閉じて再オープンして、リテラル開始の " の次に移動
601
602 ExceptionMessage(ExceptionMessage::FATAL, "Unterminated string literal appeared.","閉じられていない文字リテラルを検出しました").throwException();
603 return false;
604}
605
606
607 /*
608 * トークンの切出し
609 */
610enum Token::tagTokenType Parser::getToken(Token & token, bool allow_space)
611{
612 int ch;
613 const char * work;
614
615 do {
616 token.erase();
617 token.type = Token::ERROR;
618 token.value = 0;
619
620 //トークンスタックから切り出す
621 if(!TokenStack.empty())
622 {
623 do {
624 token = TokenStack.front();
625 TokenStack.pop_front();
626 } while(!TokenStack.empty() && !allow_space && token.type == Token::SPACE);
627
628 if(!allow_space && token.type != Token::SPACE)
629 return token.type;
630 }
631
632 //ストリームから切り出す
633 if(current == NULL || current->stream == NULL || current->stream->bad())
634 {
635 token.assign("<End of stream>");
636 return (token.type = Token::EOS);
637 }
638
639 //カレントのストリームが空になった
640 if(current->stream->eof())
641 {
642 //ファイルスタックから次のストリームを取る
643 if(!fileStack.empty())
644 {
645 if(current->stream != &cin)
646 delete current->stream;
647 delete current;
648
649 current = *fileStack.begin();
650 fileStack.pop_front();
651 }else
652 {
653 token.assign("<End of stream>");
654 return (token.type = Token::EOS);
655 }
656 }
657
658 ch = getChar();
659
660 //First(whitespaces) is [ \n\t\r/#]
661 if( (ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r') || (ch == '/') || (isHeadofLine && ch == '#'))
662 {
663 if(ch == '\n')
664 isHeadofLine = true;
665
666 if(getWhitespace(token, ch, allow_space))
667 if((token == Token::SPACE && allow_space) || !(token == Token::SPACE || token == Token::ERROR))
668 return token.type;
669
670 continue;
671 }else
672 break;
673 }while(true);
674
675 isHeadofLine = false;
676
677 token.line = current->line;
678
679 //First(identifier) is [a-zA-Z_]
680 if( (ch >='a' && ch <= 'z') || (ch >='A' && ch <= 'Z') || (ch == '_') )
681 if(getIdentifier(token, ch))
682 return Token::IDENTIFIER;
683
684 //First(integer) is [\-0-9]
685 if( (ch >='0' && ch <='9') || (ch == '-') )
686 if(getInteger(token,ch))
687 return Token::INTEGER;
688
689 //First(string) is ["']
690 if( ch == '"' || ch == '\'')
691 if(getStringLiteral(token,ch))
692 return Token::STRINGLITERAL;
693
694 //Operator
695 if(getOperator(token,ch))
696 return Token::OPERATOR;
697
698 //Punctuator
699 work = Punctuator;
700 while(*work != '\x0')
701 if( *(work++) == ch )
702 {
703 token += static_cast<char>(ch);
704 return (token.type = Token::PUNCTUATOR);
705 }
706
707 token += static_cast<char>(ch);
708 token.type = Token::UNKNOWN;
709 return Token::UNKNOWN;
710}
711
712
713 /*
714 * トークン用 ストリームオペレータ (主にテスト目的)
715 */
716ostream & operator << (ostream & out, Token & src)
717{
718 switch(src.type)
719 {
720 case Token::IDENTIFIER:
721 out << "<IDENTIFIER:["; break;
722 case Token::INTEGER:
723 out << "<INTEGER:["; break;
724 case Token::STRINGLITERAL:
725 out << "<STRINGLITERAL:["; break;
726 case Token::STRING:
727 out << "<STRING:["; break;
728 case Token::OPERATOR:
729 out << "<OPERATOR:["; break;
730 case Token::PUNCTUATOR:
731 out << "<PUNCTUATOR:["; break;
732 case Token::RESERVEDWORD:
733 out << "<RESERVEDWORD:["; break;
734 case Token::SPECIAL:
735 out << "<SPECIAL:["; break;
736 case Token::SPACE:
737 out << "<SPACE:["; break;
738 case Token::UNKNOWN:
739 out << "<UNKNOWN>"; return out;
740 case Token::ERROR:
741 out << "<ERROR>"; return out;
742 default:
743 out << "<???:[";
744 }
745
746 return out << static_cast<string &>(src) << "]("<<src.value<<")>";
747}
748
749 /*
750 * 予約語の切出し(というよりも確認)
751 */
752void Parser::getToken(const char * term) throw(Exception)
753{
754 Token token;
755
756 if(term == NULL)
757 ExceptionMessage("Internal: GetToken received an empty string as reserved word.","内
758部エラー: GetTokenに空文字列が渡されました").throwException();
759
760 getToken(token, false);
761 if(token.compare(term) != 0) {
762 lastErrorToken = token;
763 ExceptionMessage("Token [%] should be replaced by [%]","字句[%]は[%]であるべきです") << token << term << throwException;
764 }
765}
766
767void Parser::getToken(const char * first, const char * second, const char * third, const char * fourth) throw(Exception)
768{
769 getToken(first);
770 if(second != NULL)
771 getToken(second);
772 if(third != NULL)
773 getToken(third);
774 if(fourth != NULL)
775 getToken(fourth);
776}
777
778string Parser::getStreamLocation(void)
779{
780 list<tagFile *>::iterator scope;
781
782 string location;
783 char buffer[16];
784
785 if(current == 0)
786 return string("");
787
788 ::sprintf(buffer, ":%d", current->line);
789 location += current->identifier;
790 location += buffer;
791
792 if(!fileStack.empty())
793 {
794 location += " (included at ";
795
796 scope = fileStack.begin();
797 while(scope != fileStack.end())
798 {
799 ::sprintf(buffer, ":%d, ", (*scope)->line);
800 location += (*scope)->identifier;
801 location += buffer;
802
803 ++ scope;
804
805 }
806
807 location.erase(location.size()-2);
808 location += ")";
809 }
810
811 return location;
812}
813
814void Parser::pushStream(const std::string & filename, std::string strid)
815{
816 fstream * fin;
817
818 if(current != 0)
819 fileStack.push_front(current);
820
821 fin = new fstream(filename.c_str(),ios::in);
822
823 if(fin->is_open())
824 {
825 if(strid.size() == 0)
826 strid = filename;
827
828 current = new tagFile;
829 current->stream = fin;
830 current->identifier = strid;
831 current->line = 1;
832 }else
833 {
834 ExceptionMessage("File operation failure : [%]","ファイル操作に失敗しました [%]") << filename << throwException;
835 delete fin;
836 }
837}
838
839void Parser::pushStdStream(std::string strid)
840{
841 stringstream * work = new stringstream;
842 char buffer[1024];
843 int count;
844
845 //標準å…
846¥åŠ›ã®æƒ…
847報をすべて取り込む (エラー対処用に seekg/tellg を使いたい)
848 do {
849 cin.read(buffer, 1024);
850 count = cin.gcount();
851 work->write(buffer, count);
852 } while(count != 0);
853
854 if(current != 0)
855 fileStack.push_front(current);
856
857 current = new tagFile;
858 current->stream = work;
859 current->identifier = strid;
860 current->line = 1;
861}
862
863string * Parser::setLogBuffer(string * buffer)
864{
865 string * old = LogBuffer;
866 LogBuffer = buffer;
867 PutBackCount = 0;
868 return old;
869}
870
871streampos Parser::getLogBufferPos(int offset)
872{
873 streampos pos;
874
875 pos = 0;
876 if(LogBuffer != 0)
877 pos = LogBuffer->size();
878 pos += static_cast<streampos>(offset - PutBackCount);
879 return pos;
880}
881
882#ifdef CALL_EXTERNAL_PROGRAM
883void Parser::doPreProcess(const char * cmd)
884{
885 string tempfilename;
886 char buffer[1024];
887 int count;
888 fstream tempfile;
889 string work;
890 stringstream * stream;
891
892 if(current == NULL || current->stream == NULL)
893 ExceptionMessage("No stream specified for processing","処理対象となるストリームが設定されていません").throwException();
894
895
896 /* 今のストリームの内
897容をすべてテンポラリに書き出す */
898
899 strcpy(buffer,"cfgXXXXXX");
900 mktemp(buffer);
901
902 tempfilename.assign(buffer);
903 tempfile.open(tempfilename.c_str(),ios::out);
904
905 if(!tempfile.is_open())
906 ExceptionMessage("Failed to open a temporary file","テンポラリファイルの作成に失敗しました").throwException();
907
908 do {
909 current->stream->read(buffer, 1024);
910 count = current->stream->gcount();
911 tempfile.write(buffer, count);
912 } while(count != 0);
913 tempfile.close();
914
915
916 /* ストリーム差し替え */
917
918 preprocessname = tempfilename;
919 originalname = current->identifier;
920
921 if(current->stream != &cin)
922 delete current->stream;
923 stream = new stringstream;
924 current->stream = stream;
925
926
927 /* プリプロセッサの起動 & 出力の取り込み */
928
929 work = string(cmd) + " " + tempfilename;
930 VerboseMessage(" Start the external preprocessor [%]\n"," 外部プログラムを起動します [%]\n") << work;
931
932 FILE * pipe = popen(work.c_str(),"r");
933 while(feof(pipe) == 0)
934 stream->put((char)fgetc(pipe));
935
936 pclose(pipe);
937 remove(tempfilename.c_str());
938 isHeadofLine = true;
939}
940#else
941void Parser::doPreProcess(const char * cmd)
942{}
943#endif /* CALL_EXTERNAL_PROGRAM */
944
945
946ParseUnit::ParseUnit(void * _container, const char * name)
947{
948 map<string, ParseUnit *> * container;
949 string work(name);
950 string apiname;
951 string::size_type i,j;
952
953 i = 0;
954 container = reinterpret_cast<map<string, ParseUnit *> *>(_container);
955
956 do {
957 j = work.find_first_of(',', i);
958 apiname = work.substr(i, j-i);
959
960 if(container->find(apiname) != container->end())
961 ExceptionMessage("Multiple registration of [%]\n","[%]が重複して登録されようとしています") << apiname << throwException;
962 (*container)[apiname] = this;
963 i = j + 1;
964 }while(j != string::npos);
965}
966
967void ParseUnit::printList(void * _container)
968{
969 int i;
970 map<string, ParseUnit *> * container;
971 map<string, ParseUnit *>::iterator scope;
972
973 container = reinterpret_cast<map<string, ParseUnit *> *>(_container);
974 if(container->empty())
975 {
976 cerr << " " << Message("None of element registed\n", "登録されている要素はありません\n");
977 return;
978 }
979
980 i = 0;
981 scope = container->begin();
982 while(scope != container->end())
983 {
984 cerr << '[' << (*scope).first << "] ";
985
986 if(i++ >= 6)
987 {
988 i = 0;
989 cerr << '\n';
990 }
991
992 ++ scope;
993 }
994
995 if(i != 0)
996 cerr << '\n';
997}
998
999Token & ParseUnit::parseParameter(Parser & p)
1000{
1001 static Token result;
1002 Token token;
1003 int nest = 0;
1004
1005 result.type = Token::ERROR;
1006 result.value = 0;
1007 result.assign("");
1008
1009 do
1010 {
1011 p.getToken(token);
1012 if(token == Token::PUNCTUATOR)
1013 {
1014 if(token.compare("(") == 0)
1015 nest ++;
1016 else if(token.compare(")") == 0)
1017 nest --;
1018 else if(nest == 0)
1019 break;
1020 if(nest < 0)
1021 ExceptionMessage("')' appeared before '('.","対応しない閉じ括弧があります").throwException();
1022 }
1023
1024 if(result == Token::ERROR)
1025 result = token;
1026 else
1027 {
1028 result.type = Token::STRING;
1029 result += ' ';
1030 result += token;
1031 }
1032
1033 }while(true);
1034
1035 p.putBack(token);
1036 result.trim();
1037 return result;
1038}
1039
1040int ParseUnit::parseParameters(Parser & p, Directory * container, int min, int max)
1041{
1042 Token work;
1043 int count = 0;
1044
1045 if(max == 0)
1046 max = min;
1047
1048 do
1049 {
1050 Token & token = parseParameter(p);
1051 if(token.type == Token::ERROR)
1052 break;
1053
1054 if(token == Token::INTEGER)
1055 container->addChild(new Directory(token.value));
1056 else
1057 container->addChild(new Directory((string &)token));
1058
1059 count ++;
1060 p.getToken(work);
1061 }while(work.compare(",")==0 && count < max);
1062
1063 if(count < min)
1064 ExceptionMessage("Too few parameters [%/%]","パラメータの数が少なすぎます [%/%]") << count << min << throwException;
1065
1066 p.putBack(work);
1067 return count;
1068}
1069
1070int ParseUnit::parseParameters(Parser & p, Directory * container, const char * paramlist)
1071{
1072 Token work;
1073 int count;
1074 string list;
1075 string key;
1076 string::size_type head,tail;
1077
1078 list.assign(paramlist);
1079
1080 count = 0;
1081 head = 0;
1082 tail = list.find_first_of(',');
1083 key = list.substr(head,tail-head);
1084
1085 do
1086 {
1087 if(head == string::npos)
1088 ExceptionMessage("Too many parameters","パラメータの数が多すぎます").throwException();
1089
1090 Token & token = parseParameter(p);
1091 if(token.type == Token::ERROR)
1092 break;
1093
1094 if(token == Token::INTEGER)
1095 container->addChild(key,new Directory(token.value));
1096 else
1097 container->addChild(key,new Directory((string &)token));
1098
1099 if(tail != string::npos)
1100 {
1101 head = tail + 1;
1102 tail = list.find_first_of(',',head);
1103 key = list.substr(head,tail != string::npos ? tail-head : string::npos);
1104 count ++;
1105 p.getToken(work);
1106 }else
1107 break;
1108 }while(work.compare(",")==0);
1109
1110 if(tail != string::npos)
1111 ExceptionMessage("Too few parameters","パラメータの数が少なすぎます").throwException();
1112
1113 return count;
1114}
1115
1116//------
1117
1118Directory * StaticAPI::last = NULL;
1119
1120map<std::string, class ParseUnit *> & StaticAPI::container(void)
1121{
1122 static map<std::string, class ParseUnit *> _container;
1123 return _container;
1124}
1125
1126Directory * StaticAPI::allocate(Directory & container, const Token & token, const char * id, bool regist)
1127{
1128 static unsigned int assignment_count = 0;
1129 Directory * node;
1130
1131 if(!(token == Token::IDENTIFIER || token == Token::INTEGER))
1132 ExceptionMessage("Given token(%) is not suitable for an object identifier.","オブジェクトの識別名として利用できない字句(%)が指定されました") << token << throwException;
1133
1134 if(regist && (token == Token::INTEGER && token.value <= 0))
1135 ExceptionMessage("Cannot assign an ID number less or equal to 0.","0以下のID番号を設定することはできません").throwException();
1136
1137
1138 node = container.findChild(id);
1139 if(node != 0)
1140 {
1141 Directory::iterator scope;
1142
1143 scope = node->begin();
1144 while(scope != node->end())
1145 {
1146 if((*scope).first.compare(token) == 0)
1147 ExceptionMessage("Identifier % is already used.","識別名%はすでに利用されています") << token << throwException;
1148 ++ scope;
1149 }
1150 }else
1151 node = container.addChild(id);
1152
1153 node = node->addChild(token);
1154 (*node)["#order"] = assignment_count++;
1155
1156 if(token == Token::IDENTIFIER)
1157 {
1158 if(regist)
1159 {
1160 Directory * scope = container.openChild("/","identifier",token.c_str(),NULL);
1161 if(*scope == Directory::INTEGER)
1162 *node = scope->toInteger();
1163 }
1164 }else
1165 *node = token.value;
1166
1167 last = node;
1168 return node;
1169}
1170
1171//------
1172
1173map<std::string, class ParseUnit *> & Directive::container(void)
1174{
1175 static map<std::string, class ParseUnit *> _container;
1176 return _container;
1177}
1178
1179//------
1180
1181ParserComponent::ParserComponent(void) throw() : Component(PARSER)
1182{}
1183
1184ParserComponent::~ParserComponent(void) throw()
1185{}
1186
1187void ParserComponent::parseOption(Directory & container)
1188{
1189 if(findOption("h", "help"))
1190 {
1191 cerr << Message(
1192 "Static API parser\n"
1193 " -s, --source=filename : Specify the source file\n"
1194 " -idir ,--ignore-directive : Ignore directives\n"
1195 " -iapi ,--ignore-api : Ignore unknown static api\n"
1196 " -t, --through : Get unprocessed APIs through\n"
1197 " --print-api : Show registered static api list\n",
1198 "静的APIパーサ\n"
1199 " -s, --source=ファイル名 : å…
1200¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«åã‚’指定します\n"
1201 " -idir ,--ignore-directive : ディレクティブの解析を行いません\n"
1202 " -iapi, --ignore-api : 登録されていないAPIを無視します\n"
1203 " -t, --through : 処理しなかったAPIを通過させます\n"
1204 " --print-api : 登録されているAPIの一覧を表示します\n");
1205 return;
1206 }
1207
1208 if(findOption("-print-api"))
1209 {
1210 cerr << Message("List of Registerd Static API\n","静的API 一覧\n");
1211 StaticAPI::printList();
1212 return;
1213 }
1214
1215 checkOption("idir", "ignore-directive");
1216 checkOption("iapi", "ignore-api");
1217 checkOption("t", "through");
1218
1219 if(checkOption("s","source") || checkOption(DEFAULT_PARAMETER))
1220 activateComponent();
1221}
1222
1223bool ParserComponent::parseStaticAPI(Parser & p, Directory & container, Token token, const string domain)
1224{
1225 bool isParseErrorOccured = false;
1226 map<string, ParseUnit *>::iterator api;
1227 Directory * node = NULL;
1228
1229 if(token.type != Token::IDENTIFIER)
1230 return false;
1231
1232 StaticAPI::clearLastObject();
1233 node = container[PARSERESULT].addChild();
1234
1235 try {
1236 node->addChild("api",new Directory(token));
1237 node->addChild("begin",new Directory((long)p.getLogBufferPos(-(int)token.size()-1)));
1238 if(!domain.empty())
1239 node->addChild("domain", new Directory(domain));
1240
1241 api = StaticAPI::container().find(token);
1242 if(api == StaticAPI::container().end())
1243 {
1244 if(ignoreUnknownAPI)
1245 {
1246 cerr << Message("%: Unknown static api % was ignored. (skipped)\n","%: 非登録のAPI % は無視されます\n") << p.getStreamLocation() << token;
1247 do {
1248 p.getToken(token);
1249 }while(token.compare(";") != 0);
1250 node->addChild("end",new Directory((long)p.getLogBufferPos()));
1251 (*node) = (long)0;
1252 return true;
1253 }
1254 ExceptionMessage("Static API [%] is not registered in the configurator", "静的API[%]は未登録です") << token << throwException;
1255 }
1256
1257 DebugMessage(" StaticAPI [%]\n") << (*api).first;
1258
1259 p.getToken("(");
1260
1261 (*api).second->body(token, container, p, domain);
1262
1263 p.getToken(")");
1264 p.getToken(";");
1265
1266 node->addChild("end",new Directory((long)p.getLogBufferPos()));
1267 (*node) = (long)1;
1268 }
1269 catch(Exception & e)
1270 {
1271 int offset;
1272 string work;
1273 work = p.getStreamLocation() + Message(":[Error] ",":[エラー] ").str() + e.getDetails();
1274 isParseErrorOccured = true;
1275
1276 StaticAPI::dropLastObject();
1277 failCount ++;
1278
1279 offset = 0;
1280 token = p.getLastErrorToken();
1281 while (token != Token::ERROR && token != Token::EOS)
1282 {
1283 if( token == ";" )
1284 break;
1285
1286 //読み出したトークンが静的APIと同じ名前なら きっとセミコロン忘れ
1287 api = StaticAPI::container().find(token);
1288 if(api != StaticAPI::container().end())
1289 {
1290 cerr << Message("<The following error must be occured by lack of ';' at the end of previous line>\n","<次のエラーは直前行の';'忘れによる可能性が高いです>\n");
1291 offset = -(int)token.size();
1292 p.putBack(token);
1293 break;
1294 }
1295
1296 p.getToken(token);
1297 }
1298
1299 node->addChild("end",new Directory((long)p.getLogBufferPos(offset)));
1300 (*node) = (long)0;
1301
1302 cerr << work << '\n';
1303
1304 ExceptionMessage("Fatal error on Static API parsing","静的APIの構文解析に失敗しました").throwException();
1305 }
1306
1307 return true;
1308}
1309
1310/*
1311 * 処理できなかったAPIを標準出力に吐き出す
1312 */
1313void ParserComponent::throughConfigurationFile(string & log, Directory & container)
1314{
1315 Directory * node;
1316 string::size_type pos;
1317 string::size_type begin;
1318 string::size_type end;
1319
1320 pos = 0;
1321 end = 0;
1322
1323 node = container[PARSERESULT].getFirstChild();
1324 while(node != NULL)
1325 {
1326 begin = static_cast<string::size_type>((*node)["begin"].toInteger());
1327 end = static_cast<string::size_type>((*node)["end"].toInteger());
1328
1329 if(pos < begin)
1330 cout << log.substr(pos, begin - pos);
1331
1332 if(node->toInteger() == 0)
1333 {
1334 cout << log.substr(begin, end - begin);
1335 }else
1336 {
1337 for(pos = begin; pos < end; ++pos)
1338 if( log.at(pos) == '\n' )
1339 cout << '\n';
1340 }
1341 node = node->getNext();
1342 }
1343
1344 if(end < log.size())
1345 cout << log.substr(end);
1346
1347 ExceptionMessage("","").throwException();
1348}
1349
1350
1351void ParserComponent::body(Directory & container)
1352{
1353 Token token;
1354 Parser p(container);
1355 string logbuffer;
1356 OptionParameter::OptionItem item;
1357 unsigned int itemcount = 0;
1358
1359 failCount = 0;
1360
1361 //idirオプションの処理
1362 if(findOption("idir","ignore-directive"))
1363 p.disable(Parser::DIRECTIVE);
1364
1365 ignoreUnknownAPI = findOption("iapi", "ignore-api");
1366
1367 if(findOption("t","through"))
1368 {
1369 p.setLogBuffer(&logbuffer);
1370 ignoreUnknownAPI = true;
1371 }
1372
1373 //å…
1374¥åŠ›ã‚½ãƒ¼ã‚¹
1375 item = getOption("s", "source");
1376 item.mergeItem(getOption(DEFAULT_PARAMETER));
1377 if(item.countParameter() == 0)
1378 {
1379 p.pushStdStream(Message("Standard Input","標準å…
1380¥åŠ›").str());
1381 VerboseMessage("Starting parse with standard input\n","標準å…
1382¥åŠ›ã‹ã‚‰ã®å­—句解析を開始しました\n");
1383 }
1384
1385 try{
1386 do {
1387 if(item.hasParameter())
1388 {
1389 VerboseMessage("Starting parse with file[%]\n","ファイル[%]の字句解析を開始しました\n") << item[itemcount];
1390 p.pushStream(item[itemcount]);
1391 }
1392
1393 this->parse(p, container);
1394
1395 if(p.getToken(token) != Token::EOS)
1396 ExceptionMessage("Buffer has remaining tokens, parsing is not yet finished", "パースが中断されました").throwException();
1397
1398 if(failCount != 0)
1399 ExceptionMessage("Total % failures found in this configuration.","%個の障害があります") << failCount << throwException;
1400
1401 VerboseMessage("Parse finished\n","字句解析は正常に終了しました\n");
1402
1403 } while(++itemcount < item.countParameter());
1404
1405 if(findOption("t","through"))
1406 throughConfigurationFile(logbuffer,container);
1407
1408 container[PARSERESULT].erase();
1409 }
1410 catch(Exception & e)
1411 {
1412 string work;
1413
1414 work = p.getStreamLocation() + Message(":[Error] ",":[エラー] ").str() + e.getDetails();
1415 ExceptionMessage(work.c_str()).throwException();
1416 }
1417}
1418
1419 // オプションノードから割付方法を取得する
1420enum Common::tagAssignmentOrder Common::parseOrder(Directory * node)
1421{
1422 Directory * scope;
1423 int i;
1424
1425 //割当パラメータ解析
1426 i = FCFS;
1427 if(node != 0)
1428 {
1429 scope = node->getFirstChild();
1430 while(scope != 0)
1431 {
1432 string param = scope->toString();
1433 if(param.compare("alphabetic") == 0 || param.compare("ALPHABETIC") == 0)
1434 i = (i & 0xf0) | ALPHABETIC;
1435 else if(param.compare("fcfs") == 0 || param.compare("FCFS") == 0)
1436 i = (i & 0xf0) | FCFS;
1437 else if(param.compare("reverse") == 0 || param.compare("REVERSE") == 0)
1438 i |= REVERSE;
1439
1440 scope = scope->getNext();
1441 }
1442 }
1443
1444 return static_cast<enum tagAssignmentOrder>(i);
1445}
1446
1447 // オプションノードから割付方法を取得する
1448enum Common::tagAssignmentOrder Common::parseOrder(OptionParameter::OptionItem item)
1449{
1450 Directory node;
1451 unsigned int i;
1452
1453 for(i=0;i<item.countParameter();++i)
1454 node.addChild(item[i]);
1455
1456 return parseOrder(&node);
1457}
1458
1459 //ID値のアサインメント
1460 // (他の場所からも使うのでここに移動)
1461int Common::assignID(Directory & container, const char * category, const char * top, enum tagAssignmentOrder order)
1462{
1463 Directory * node = 0;
1464 Directory * scope = 0;
1465 Directory * work = 0;
1466 set<int> idpool;
1467 map<int, Directory *> sorter;
1468 map<int, Directory *>::iterator p_sorter;
1469 int i;
1470
1471 //下準備
1472 node = container.findChild(top,category,NULL);
1473 if(node == 0)
1474 return 0;
1475
1476 for(i=1;i< (signed int) node->size() + 32; i++)
1477 idpool.insert(i);
1478
1479 //割付順の決定と,割当済みIDの削除
1480 i = 0;
1481 scope = node->getFirstChild();
1482 while(scope != 0)
1483 {
1484 if( *scope == Directory::INTEGER )
1485 idpool.erase(*scope);
1486 else
1487 {
1488 //重複名称の存在チェック
1489 work = container.openChild("/","identifier",scope->getKey().c_str(),NULL);
1490 if( *work == Directory::INTEGER)
1491 {
1492 VerboseMessage("Assigning the same ID (%) since the name (%[%]) is duplicated\n","ID番号(%)を異種同名のオブジェクト(%[%])に割り当てます.\n") << work->toInteger() << scope->getKey() << category;
1493 idpool.erase(*scope = work->toInteger());
1494 } else
1495 {
1496 //割当方法に従って割当候補に追加
1497 switch(order)
1498 {
1499 case ALPHABETIC:
1500 sorter[i++] = scope;
1501 break;
1502 case REVERSE_ALPHABETIC:
1503 sorter[i--] = scope;
1504 break;
1505 case FCFS:
1506 default:
1507 sorter[scope->openChild("#order")->toInteger()] = scope;
1508 break;
1509 case REVERSE_FCFS:
1510 sorter[-scope->openChild("#order")->toInteger()] = scope;
1511 break;
1512 }
1513 }
1514 }
1515 scope = scope->getNext();
1516 }
1517
1518 //ID割当
1519 p_sorter = sorter.begin();
1520 while(p_sorter != sorter.end())
1521 {
1522 scope = (*p_sorter).second;
1523 if( !(*scope == Directory::INTEGER) )
1524 {
1525 i = *(idpool.begin());
1526 idpool.erase(idpool.begin());
1527
1528 work = container.openChild("/","identifier",scope->getKey().c_str(),NULL);
1529 *work = i;
1530 *scope = i;
1531 }
1532 ++ p_sorter;
1533 }
1534
1535 //割当表作成
1536 if(node->size() != 0 && VerboseMessage::getVerbose())
1537 {
1538 VerboseMessage("Object ID assignment list [%]\n","オブジェクトID割付表 [%]\n") << category;
1539
1540 sorter.clear();
1541 scope = node->getFirstChild();
1542 while(scope != 0)
1543 {
1544 sorter[scope->toInteger()] = scope;
1545 scope = scope->getNext();
1546 }
1547
1548 p_sorter = sorter.begin();
1549 while(p_sorter != sorter.end())
1550 {
1551 VerboseMessage(" % : %\n") << setw(3) << (*p_sorter).first << (*p_sorter).second->getKey();
1552 ++ p_sorter;
1553 }
1554 }
1555
1556 //妥当性の判定
1557 if((signed)node->size()+1 != *(idpool.begin()))
1558 ExceptionMessage("Discontinuous % ID assignment occured","不連続なオブジェクトID(%)") << category << throwException;
1559
1560 return node->size();
1561}
1562
Note: See TracBrowser for help on using the repository browser.