📄 parser.cpp
字号:
#include <string>using std::string;#include "token.h"extern CToken* yylex();extern FILE* yyin;string g_header;bool g_lineinfo;bool g_debug;std::map<string,string> g_macros;class ETEOF{};class ETUnmatch{public: ETUnmatch(int _exp, CToken* _enc) : exp(_exp), enc(_enc) { } string to_string (int c) { char buff[10]; if(c<MIN_TOKEN) sprintf(buff,"'%c'",c); else sprintf(buff,"%d",c); return string(buff); } int exp; CToken* enc;};class Parser{public: int parse(const char*);private: int NextToken(bool if_throw=true) ; CToken* MatchAny(); CToken* Match(int t); CToken* MatchPair(int,int); CToken* MatchPair(int,int,string&); CToken* parse_template(); CToken* parse_component(); CToken* parse_connect(); CToken* parse_varid(); CToken* parse_compid(); CToken* parse_typename(); CToken* parse_port(string &, bool&); CToken* parse_funct_body(); CToken* parse_arglist(string&, string&); std::vector<CToken*> m_tokens; std::vector<CToken*> m_program; std::vector<CToken*>::iterator m_iter; CToken* m_template; ComponentClass* m_current_component; ComponentTable* m_component_table; FILE* m_outfile; void WriteProgram(); string m_hfilename;};int Parser::NextToken(bool if_throw){ if(m_iter==m_tokens.end()) { if(if_throw) throw ETEOF(); else return 0; } else return (*m_iter)->type;}CToken* Parser::MatchAny(){ CPort* port; CToken* t = *m_iter; m_iter++; if(m_iter!=m_tokens.end()&&(*m_iter)->type==VARID) { if(m_current_component!=NULL) { for(unsigned int i=0;i<m_current_component->tmpl_args.size();i++) { if( (*m_iter)->GetID() == m_current_component->tmpl_args[i]) { (*m_iter)->type=ARGID; //printf("line: %d, argid: %s\n",(*m_iter)->lineno,(*m_iter)->text.c_str()); break; } } } if(t->type!=SCOPE&&t->type!='.'&&t->type!=DOTSTAR&&t->type!=ARROWSTAR&&t->type!=ARROW) { if(ComponentClass::Lookup((*m_iter)->GetID())!=NULL) { //printf("convert '%s' to COMPID\n",(*m_iter)->GetID().c_str()); (*m_iter)->type=COMPID; } if(m_current_component!=NULL && (port=m_current_component->LookupPort((*m_iter)->GetID()))!=NULL ) { //printf("convert '%s' to PORTID\n",(*m_iter)->GetID().c_str()); (*m_iter)->type=PORTID; } } } return t;};CToken* Parser::Match(int t) { if(t!=NextToken()) throw ETUnmatch(t,*m_iter); else return MatchAny();}CToken* Parser::MatchPair(int left, int right){ CToken *s, *t; s=t=Match(left); int level=0; while(level!=0||NextToken()!=right) { if(NextToken()==right)level--; if(NextToken()==left)level++; t->sibling=MatchAny(); t=t->sibling; } t->sibling=MatchAny(); t=t->sibling; return s;}CToken* Parser::MatchPair(int left, int right, string& text){ CToken *s, *t; s=t=Match(left); text = t->text; int level=0; while(level!=0||NextToken()!=right) { if(NextToken()==right)level--; if(NextToken()==left)level++; t->sibling=MatchAny(); t=t->sibling; text += t->text; } t->sibling=MatchAny(); t=t->sibling; text += t->text; return s;}int Parser::parse(const char* filename){ yyin= fopen(filename,"r"); if(yyin==NULL) { printf("error: cannot open file '%s'\n", filename); return 2; } CTranslation::New(); CTranslation::Current()->filename=filename; CToken::New(CTranslation::Current()); // read all tokens into m_tokens while( (yylex()) != NULL ) { m_tokens.push_back(CToken::Current()); } /*for(unsigned int i=0;i<m_tokens.size();i++) { m_tokens[i]->Dump(); }*/ fclose(yyin); g_header = "#include <assert.h> \n #include<vector> \n" "template <class T> class compcxx_array { public: \n" "virtual ~compcxx_array() { for (typename std::vector<T*>::iterator i=m_elements.begin();i!=m_elements.end();i++) delete (*i); } \n"
"void SetSize(unsigned int n) { for(unsigned int i=0;i<n;i++)m_elements.push_back(new T); } \n"
"T& operator [] (unsigned int i) { assert(i<m_elements.size()); return(*m_elements[i]); } \n"
"unsigned int size() { return m_elements.size();} \n"
"private: std::vector<T*> m_elements; }; \n"
"class compcxx_component; \n"
"template <class T> class compcxx_functor {public: \n" "void Connect(compcxx_component&_c, T _f){ c.push_back(&_c); f.push_back(_f); } \n"
"protected: std::vector<compcxx_component*>c; std::vector<T> f; }; \n"
"class compcxx_component { public: \n"; string ofilename = filename; m_hfilename=ofilename; unsigned int pos = ofilename.rfind('.'); ofilename.erase(pos+1); m_hfilename.erase(pos); m_hfilename = string("compcxx_") + m_hfilename + ".h"; ofilename+="cxx"; //printf("output file name:%s\n",ofilename.c_str()); m_outfile=fopen(ofilename.c_str(),"w"); if(m_outfile==NULL) { printf("cannot open output file '%s'\n",ofilename.c_str()); return 1; } // starting parsing here m_iter=m_tokens.begin(); int type; bool line_info=true; CToken* token; parsing: m_current_component = NULL; m_component_table = NULL; try { while( (type=NextToken(false))!=0) { assert(m_current_component==NULL); assert(m_component_table==NULL); switch(type) { case TEMPLATE: token=parse_template(); break; case COMPONENT: token=parse_component(); break; case CONNECT: token=MatchAny(); CTranslation::Error(token,4, "connect statements must appear within a function\n"); break; case INPORT: case OUTPORT: token=MatchAny(); CTranslation::Error(token,5, "port must be declared within a component\n"); break; case COMPID: token= parse_compid() ; break; case VARID: token = parse_varid(); break; case TYPENAME: token = parse_typename(); break; default: token=MatchAny(); } if(token!=NULL) { if(line_info==true) { token->line_info=true; line_info=false; } m_program.push_back(token); } else line_info=true; } } catch( ETUnmatch& e ) { CTranslation::Error(e.enc, 3, "syntax error -- expected: %s, encountered: %s\n", e.to_string(e.exp).c_str(), e.to_string(e.enc->type).c_str()); line_info=true; goto parsing; } catch( ETEOF & ) { CTranslation::Error(NULL, 2, "unexpected end-of-file\n"); } if(CTranslation::ErrorCount()) { printf("%d error(s).\n",CTranslation::ErrorCount()); } WriteProgram(); fclose(m_outfile); m_outfile=fopen(m_hfilename.c_str(),"w+"); if(m_outfile==NULL) { printf("cannot open %s\n",m_hfilename.c_str()); return 1; } fprintf(m_outfile,"%s};\n",g_header.c_str()); fclose(m_outfile); return CTranslation::ErrorCount();}CToken* Parser::parse_template(){ CToken* t = Match(TEMPLATE); t->AppendChild( MatchPair('<','>') ); if(NextToken()==TEMPLATE) { t->AppendChild(Match(TEMPLATE)); t->AppendChild(MatchPair('<','>')); } return t;}CToken* Parser::parse_component(){ int token; string port_name, comp_name; string return_type, full_list, arg_list; bool array; CToken* comp = Match(COMPONENT); CToken* comp_decl = CToken::New(comp,component_declaration); CToken* tmpl = NULL; CToken* p = NULL; if(!m_program.empty()&&m_program.back()->type==TEMPLATE) { tmpl = m_program.back(); m_program.pop_back(); comp_decl->AppendChild(tmpl); comp->lineno=tmpl->lineno; tmpl->text = string("/*") + tmpl->text; assert(tmpl->last_child!=NULL); tmpl->last_child->text += "*/"; } comp->line_info=true; comp_decl->AppendChild(comp); CToken* t = Match(VARID); t->type=MAINID; comp_decl->AppendChild(t); comp_name = t->GetID(); m_current_component = ComponentClass::Lookup(comp_name); if(m_current_component!=NULL) { CTranslation::Error(t,6,"component '%s' has already been defined\n",comp_name.c_str()); comp_name+='_'; } m_current_component = ComponentClass::New(comp,comp_name); if(g_debug)printf("component %s\n",comp_name.c_str()); if(tmpl!=NULL)m_current_component->AnalyzeTemplate(tmpl); m_component_table = m_current_component; if(NextToken()==';') { CTranslation::Error(t,7,"foward component declaration not necessary\n"); comp_decl->AppendChild(MatchAny()); return comp; } if(NextToken()==':') { CToken* t = Match(':'); t->text += "public " COMPCXX "component, "; comp_decl->AppendChild(t); } else { CToken* t = CToken::New(comp,UNKNOWN); t->text = ": public " COMPCXX "component "; comp_decl->AppendChild(t); } while(NextToken()!='{') comp_decl->AppendChild(MatchAny()); comp_decl->AppendChild(Match('{')); while( (token=NextToken())!='}') { switch(token) { case COMPONENT: CTranslation::Error(*m_iter,8,"nested component not permitted\n"); while(NextToken()!=';') MatchAny(); MatchAny(); break; case INPORT: t = parse_port( port_name, array); comp_decl->AppendChild(t); break; case OUTPORT: t = parse_port( port_name, array); p = CToken::New(t, outport_declaration); p->text = port_name; p->AppendChild(t); comp_decl->AppendChild(p); if(m_current_component!=NULL&&m_current_component->composite&&array) { CTranslation::Error(t,19,"a composite component cannot have outport arrays\n"); } break; case CONNECT: MatchAny(); CTranslation::Error(NULL,4, "connect statements must appear within a function\n"); break; case COMPID: comp_decl->AppendChild(parse_compid()); break; case VARID: comp_decl->AppendChild(parse_varid()); break; case CLASS: while(NextToken()!=';'&&NextToken()!='{') comp_decl->AppendChild(MatchAny()); if(NextToken()=='{') comp_decl->AppendChild(MatchPair('{','}')); else comp_decl->AppendChild(Match(';')); break; default: comp_decl->AppendChild(MatchAny()); } }; CToken* tend = Match('}'); if(g_debug)printf("end component\n"); comp_decl->AppendChild(CToken::New(tend,end_of_component_declaration)); comp_decl->AppendChild(tend); if(NextToken()==';') comp_decl->AppendChild(Match(';')); m_current_component->AddToken(comp_decl); m_current_component=NULL; m_component_table=NULL; return NULL; }CToken* Parser::parse_port(string& port_name, bool& array)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -