?? parse.cpp
字號:
}
tLast=index;
cur_rule.push_back(index);
match(Lex::ASC);
break;
case '{':
{
sint32 thisruleno=lex.lineno;
eat_act( cur_rule );
match('}');
if( Lex::ID==lookahead || Lex::ASC==lookahead
|| '{'==lookahead)
{ // 嵌入式動作(panelly action).
/* 在產生式集中插入一個 '@N->空' 樣式的產生式 */
char tmp_str[9];
itoa(panel_act_num++,tmp_str,10);
string panel_act(tmp_str);
panel_act.insert(0,1,'@');
index=insert_Vns(panel_act,-1);
cur_rule.push_back(index);
vector<sint32> tmp_ruler;
tmp_ruler.push_back(index);
insert_ruler(tmp_ruler,0,0,thisruleno);
}
else
{
IsHaveAct=True;
Continue=False;
}
}
break;
default:
Continue=False;
break;
}
}// while
return tLast;
}
Void
Parse::eat_act(const vector<sint32> &cur_rule)
{ // 往faction文件中寫入動作.
register sint32 c,c2;
register sint32 count=1; // '{ }'的配對情況.
const sint32 rule_len=cur_rule.size();
// 有必要時輸出相應的產生式以便于觀察.
faction<<"case "<<nRules<<": /* ";
/* */
assert( cur_rule.size() > 0);
assert( cur_rule[0] >= STARTNONT );
faction<< Vns[cur_rule[0]-STARTNONT]<<" -> ";
for(sint32 i=1;i<rule_len;++i)
{
if(cur_rule[i]>=STARTNONT)
faction<< Vns[cur_rule[i]-STARTNONT]<<' ';
else
faction<< Vts[cur_rule[i]]<<' ';
}
faction<<" */";
faction<<"\n#line "<<lex.lineno<<" \""<<cmd.get_ifname()<<"\"\n";
/* */
faction.put('{');
do{
c=lex.pf.get();
switch(c)
{
case '{':
++count;
faction.put('{');
break;
case '}':
--count;
faction.put('}');
break;
case '\n':
++lex.lineno;
faction.put('\n');
break;
case '$':
{
/* 如果產生式中的符號存在 %type <xxx> 定義,則,
* $$ 替換為 yyval.xxx, $N 替換為 yyvs[N - rule_len+1].xxx.
* 否則
* $$ 替換為 yyval; $N 替換為 yyvs[N - rule_len+1];
* $<xxx>$ 替換為 yyval.xxx ,$<xxx>N 替換為 yyvs[N - rule_len+1].xxx
*
* 其中的 N 可正可負,全不可大于 rule_len - 1,即 N <= rule_len-1;
*/
c2=lex.pf.get();
sint32 code=0,uflag,sign;
err_msg.str(""); // 清空err_msg.
if( isdigit(c2) )
{
sign = 1;
L1:
while( isdigit(c2) )
{
code=code*10+c2-'0';
c2=lex.pf.get();
}
code *= sign;
lex.pf.unget();
if ( code >0 && code <= rule_len -1 )
{
if(cur_rule[code] >= STARTNONT)
uflag=nontUnion[cur_rule[code]-STARTNONT];
else
uflag=tUnion[cur_rule[code]];
if( -1 != uflag )
err_msg<<" yyvs["<<code - rule_len+1<<"]."<<sUnion[uflag].c_str()<<' ';
else
err_msg<<" yyvs["<<code - rule_len+1<<"] ";
//faction.write(err_msg.str(),err_msg.size());
faction.write(err_msg.str().c_str(),err_msg.str().size());
}
else if(code <= 0 && code <= rule_len - 1)
{
err_msg<<" yyvs["<<code - rule_len+1<<"] ";
faction.write(err_msg.str().c_str(),err_msg.str().size());
}
else
{
err_msg<<"$"<<code<<" 超過正常的范圍.";
showErr();
}
}
else if( '$'==c2 )
{
if(cur_rule[0] >= STARTNONT)
uflag=nontUnion[cur_rule[0]-STARTNONT];
else
uflag=tUnion[cur_rule[0]];
if( -1 != uflag )
err_msg<<" yyval."<<sUnion[uflag].c_str()<<' ';
else
err_msg<<" yyval ";
faction.write(err_msg.str().c_str(),err_msg.str().size());
}
else if( '-'==c2 )
{
c2=lex.pf.get();
if(isdigit(c2))
{
sign=-1;
goto L1;
}
else
{
lex.pf.unget();
err_msg<<" '$' 聲明格式錯誤.";
showErr();
}
}
else if( '<'==c2 )
{
string str;
while((c2=lex.pf.get())!='>' && Lex::ENDOFFILE!=c2)
str+=c2;
if(Lex::ENDOFFILE==c2)
{
err_msg<<"非正常的文件結尾.";
fatal();
}
c2=lex.pf.get();
if('$'==c2)
{
err_msg<<" yyval."<<str.c_str()<<' ';
faction.write(err_msg.str().c_str(),err_msg.str().size());
}
else if(isdigit(c2))
{
sign=1;
L2:
while(isdigit(c2))
{
code=code*10+c2-'0';
c2=lex.pf.get();
}
code *= sign;
lex.pf.unget();
if( code <= rule_len - 1 )
{
err_msg<<" yyvs["<<code-rule_len+1<<"]."<<str.c_str()<<' ';
faction.write(err_msg.str().c_str(),err_msg.str().size());
}
else
{
err_msg<<"$"<<code<<" 超過正常的范圍.";
showErr();
}
}
else if('-'==c2)
{
c2=lex.pf.get();
if (isdigit(c2))
{
sign=-1;
goto L2;
}
else
{
lex.pf.unget();
err_msg<<" '$' 聲明格式錯誤.";
showErr();
}
}
}
else
{
lex.pf.unget();
err_msg<<" '$' 聲明格式錯誤.";
showErr();
}
err_msg.str("");
break;
}
case '/':
if( '*' == lex.pf.peek() || '/'==lex.pf.peek())
{
lex.pf.unget();
if(!eat_up_comment(faction,lex.pf,lex.lineno,Lex::ENDOFFILE))
{
err_msg<<"在注釋中出現錯誤.";
fatal();
}
}
else
faction.put('/');
break;
case '\"':
{ // string.
lex.pf.unget();
if(!eat_up_string(faction,lex.pf,lex.lineno,Lex::ENDOFFILE))
{
err_msg<<"文件非法終止.";
fatal();
}
}
break;
case '\'': // 處理 '}' or '{' '$' 的特殊情況.
faction.put(c);
c2=lex.pf.peek();
if( '{'==c2 || '}'==c2 || '$'==c2 )
{
faction.put(lex.pf.get());
}
break;
case Lex::ENDOFFILE:
err_msg<<"第 "<<nRules<<" 個產生式的動作未完成.";
fatal();
break;
default:
faction.put(c);
break;
}// switch()
}while(0!=count);
faction<<" break;\n";
lookahead='}';
}
//prec : /* empty */
// | PREC ID
// | PREC ID act
// ;
sint32
Parse::prec(const vector<sint32> &cur_rule, Bool &IsHaveAct)
{ // Error 則返回 -1 .
if( Lex::PREC == lookahead)
{
sint32 index=-1;
match(Lex::PREC);
if(Lex::ID == lookahead ||
Lex::ASC==lookahead)
{
if(isinVns(lex.strval)==-1)
{
index=isinVts(lex.strval);
if( index==-1 && Lex::ASC==lookahead)
{
//index = insert_Vts(lex.strval,0,0,-1,-1);
index = insert_Vts(lex.strval,0,0,-1,lex.numval);
}
else if(index==-1)
{
err_msg<<" '"<<lex.strval<<"' 并非有效的終結符.";
showErr();
}
}
else
{
err_msg<<" '%prec' 后不能跟上非終結符 '"<<lex.strval<<"' .";
showErr();
}
match(lookahead);
if ('{'==lookahead)
{ // %prec ID 后的動作.
if (IsHaveAct)
{
err_msg<<" '%prec' 前后不能同時進行動作說明.";
showErr();
}
IsHaveAct=True;
eat_act(cur_rule);
//match('}');
}
else
lex.ungettoken();
}
else
{
err_msg<<"關鍵字 '%prec' 后缺少標識符.";
showErr();
lex.ungettoken();
}
match(lookahead);
return index;
}
else
return -1;
}
/*
* 如果token與lookahead配對則讀入下一符號,否則
* 返回False.
*/
/*
Bool
Parse::match(sint32 token)
{
if(lookahead==token)
{
lookahead=lex.gettoken();
return True;
}
else
{
assert(0);
return False;
}
}
*/
Void
Parse::showErr()
{
++nerror;
cout<<'('<<lex.lineno<<')'<<" 警告:"<<err_msg.str() <<'\n';
err_msg.str("");
}
/*
* 出現較嚴重錯誤時調用 fatal(),以清除一些失敗時
* 不應該存在的數據,如果有內容寫入文件,則清除文件內容.
*/
Void
Parse::fatal()
{
//wcout<<"致命錯誤!\n";
cout<<'('<<lex.lineno<<')'<<" 錯誤:"<<err_msg.str()<<'\n';
// of_cpp ,of_h
err_msg.str("");
exit(1);
}
sint32
Parse::size(const vector<Bool> &vec)
{
sint32 siz=0;
vector<Bool>::const_iterator citer=vec.begin();
while(citer != vec.end())
{
siz+=(*citer==True ? 1 : 0);
++citer;
}
return siz;
}
/*
設G=(VN,VT,P,S)是一文法,我們說G中的一個符號X∈VN∪VT是有用的,
是指X至少出現在一個句子的推導過程中,即X必須同時滿足以下兩個條件:
(1) 存在α,β∈V*,有
S
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -