⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cppcodegenerator.cpp

📁 用于词法分析的词法分析器
💻 CPP
字号:
/*  $Id: CppCodeGenerator.cpp,v 1.15 1997/02/22 09:00:23 matt Exp $  C++ code generator class.  (c) Matt Phillips 1996.  */#include "CppCodeGenerator.h"CppCodeGenerator::CppCodeGenerator (const FooObject &s,				    istream &cf, ostream &h,				    ostream &b) :  scandef (s), codefrags (cf, "cpp"), header (h), body (b), errors (0),  errorProduction ("ElexState::DefaultErrorProduction"){  doHeader ();  doBody ();}// output chr as 'c' is ASCII or as a number if not.void CppCodeGenerator::doOutputChar (unsigned char chr){  if (chr < 32 || chr > 127)    body << (unsigned)chr;  else if (chr == '\\')    body << "'\\\\'";  else    body << '\'' << (char)chr << '\'';}void CppCodeGenerator::doHeader (){  // includes  header << "#include <cppscan/ElexScanner.h>\n\n";  // do header includes  codefrags.nextFrag ();  if (codefrags.hasFrag ())  {    codefrags.outputFrag (header);    header << endl;  }  // class  header << "class " << scandef.getAttrString ("name") << " : public ";  // base class  if (scandef.hasAttr ("base"))    header << scandef.getAttrString ("base") << endl;  else    header << "ElexScanner\n";  header << "{\npublic:\n\n";  doTokenSymbols ();  doProdSymbols ();  // constructor  header << "  " << scandef.getAttrString ("name") <<    " (XInputStream &i);\n\n";  header << "  virtual int invokeProduction (int prod);\n\n";  doProdDecls ();  header << "};\n";}// do the enum declarations for productionsvoid CppCodeGenerator::doProdSymbols (){  const FooObject::Objects &productions =    scandef.getAttrs ("productions");  if (productions.nItems () > 0)  {    header << "  enum {";    for (FooObject::Objects::Iterator p (productions); p; )    {      header << "Prod" << p.ref ().getAttr ();      p++;      if (p) header << ", ";    }    header << "};\n\n";  }}// do the enum declarations for token symbolsvoid CppCodeGenerator::doTokenSymbols (){  const FooObject::Objects &tokens = scandef.getAttrs ("tokens");  if (tokens.nItems () > 0)  {    header << "  enum {";    for (FooObject::Objects::Iterator i (tokens); i; )    {      header << i.ref ().getAttr ();      i++;      if (i)	header << ", ";    }    header << "};\n\n";  }}// do the production member function declarationsvoid CppCodeGenerator::doProdDecls (){  const FooObject::Objects &productions =    scandef.getAttrs ("productions");  for (FooObject::Objects::Iterator p (productions); p; p++)  {    header << "  int prod" << p.ref ().getAttr () << " ();\n";  }}void CppCodeGenerator::doBody (){  const string &scannerName = scandef.getAttrString ("name");  body << "static ElexState states [];\n\n";  body << "//////////////////// Edges ////////////////////\n\n";  doEdgeLists ();  body << "//////////////////// States ////////////////////\n\n";  doStates ();  body << "\n////////////////// Productions /////////////////\n\n";  body << "typedef int (" << scannerName << "::*ProdFunc) ();\n\n";  doProdFuncsTable (scannerName);  body << "int " << scannerName << "::invokeProduction (int prod)\n";  body << "{\n  return (this->*(funcs [prod])) ();\n}\n\n";  doProdBodies (scannerName);  body << "////////////////// Constructor /////////////////\n\n";  body << "static ElexScannerData scannerData = {states, " << errorProduction << "};\n\n";  body << scannerName << "::" << scannerName <<    " (XInputStream &i) :\n";  body << "  ElexScanner (scannerData, i) {}\n\n";}// do the edge list definitions for all statesvoid CppCodeGenerator::doEdgeLists (){  const FooObject::Objects &states = scandef.getAttrs ("states");  for (FooObject::Objects::Iterator s (states); s; s++)  {    const string &stateNo = s.ref ().getAttrString ("state");    const FooObject::Objects &edges = s.ref ().getAttrs ("edges");        // output any edges for this state    if (edges.nItems () > 0)    {      body << "static ElexEdge state" << stateNo << "_edgelist [] =\n{\n";            doEdgeList (edges, stateNo);            body << "};\n";            body << "static ElexEdges state" << stateNo <<	"_edges = {state" << stateNo << "_edgelist, " <<	edges.nItems () << "};\n\n";    }  }}// do <edges> for state <stateNo>void CppCodeGenerator::doEdgeList (const FooObject::Objects &edges,				   const string &stateNo){  for (FooObject::Objects::Iterator e (edges); e; )  {    const FooObject &edge = e.ref ();    const string &range = edge.getAttrString ("range");        body << "  {";    doOutputChar (range [0]);    body << ", ";        // if range is of form 'l-u', then output upper, otherwise    // output the lower again    doOutputChar (range.length () > 1 ? range [2] : range [0]);    body << ", states + " << edge.getAttrString ("target") << "}";        e++;    if (e)      body << ",\n";    else      body << endl;  }}// do the states tablevoid CppCodeGenerator::doStates (){  body << "static ElexState states [] =\n{\n";    const string &scannerName = scandef.getAttrString ("name");  const FooObject::Objects &states = scandef.getAttrs ("states");  for (FooObject::Objects::Iterator s (states); s; )  {    const FooObject &state = s.ref ();    const string &stateNo = state.getAttrString ("state");    const string &prodName = state.getAttrString ("production");    const FooObject::Objects &edges = state.getAttrs ("edges");    if (state.hasAttr ("edges"))      body << "  {&state" << stateNo << "_edges, ";    else      body << "  {0, ";    if (prodName.length () > 0)      body << scannerName << "::Prod" << prodName;    else      body << "ElexState::NoProduction";    body << "}";    s++;    if (s)      body << ",\n";    else      body << endl;  }  body << "};\n";}// do the production member functions table: maps production number to// member function.  also looks for the error production, and sets// errorProduction if found.void CppCodeGenerator::doProdFuncsTable (const string &scannerName){  const FooObject::Objects &productions =    scandef.getAttrs ("productions");  body << "static ProdFunc funcs [] =\n{\n";  int first = 1;  for (FooObject::Objects::Iterator p (productions); p; )  {    const string &prodName = p.ref ().getAttr ();    body << "  " << scannerName << "::prod" << prodName;    if (prodName == "error")      errorProduction = scannerName + "::Prod" + prodName;    p++;    if (p)      body << ",\n";    else      body << endl;  }    body << "};\n\n";}// inserts the production bodies from the code fragsvoid CppCodeGenerator::doProdBodies (const string &scannerName){  const FooObject::Objects &productions =    scandef.getAttrs ("productions");  for (FooObject::Objects::Iterator p (productions); p; p++)  {    body << "int " << scannerName << "::prod" << p.ref ().getAttr () <<      " ()\n{\n";    codefrags.nextFrag ();    if (codefrags.hasFrag ())      codefrags.outputFrag (body);    else    {      cerr << "warning: no code for production " <<	p.ref ().getAttr () << endl;      body << "// *** Missing code fragment\n";    }    body << "}\n\n";  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -