#ifndef ACTIONSANDRULES_H #define ACTIONSANDRULES_H ///////////////////////////////////////////////////////////////////// // ActionsAndRules.h - declares new parsing rules and actions // // ver 2.2 // // Language: Visual C++ 2008, SP1 // // Platform: Dell Precision T7400, Vista Ultimate SP1 // // Application: Prototype for CSE687 Pr1, Sp09 // // Author: Jim Fawcett, CST 4-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////// /* Module Operations: ================== This module defines several action classes. Its classes provide specialized services needed for specific applications. The modules Parser, SemiExpression, and Tokenizer, are intended to be reusable without change. This module provides a place to put extensions of these facilities and is not expected to be reusable. Public Interface: ================= Toker t(someFile); // create tokenizer instance SemiExp se(&t); // create a SemiExp attached to tokenizer Parser parser(se); // now we have a parser Rule1 r1; // create instance of a derived Rule class Action1 a1; // create a derived action r1.addAction(&a1); // register action with the rule parser.addRule(&r1); // register rule with parser while(se.getSemiExp()) // get semi-expression parser.parse(); // and parse it Build Process: ============== Required files - Parser.h, Parser.cpp, ScopeStack.h, ScopeStack.cpp, ActionsAndRules.h, ActionsAndRules.cpp, ConfigureParser.cpp, ItokCollection.h, SemiExpression.h, SemiExpression.cpp, tokenizer.h, tokenizer.cpp Build commands (either one) - devenv CodeAnalysis.sln - cl /EHsc /DTEST_PARSER parser.cpp ActionsAndRules.cpp \ semiexpression.cpp tokenizer.cpp /link setargv.obj Maintenance History: ==================== ver 2.2 : 07 Mar 16 - changed actions and rules to match midterm question, e.g., find #includes ver 2.1 : 15 Feb 16 - small functional change to a few of the actions changes display strategy - preface the (new) Toker and SemiExp with Scanner namespace ver 2.0 : 01 Jun 11 - added processing on way to building strong code analyzer ver 1.1 : 17 Jan 09 - changed to accept a pointer to interfaced ITokCollection instead of a SemiExpression ver 1.0 : 12 Jan 06 - first release */ // #include #include #include #include #include "Parser.h" #include "../SemiExp/itokcollection.h" #include "../ScopeStack/ScopeStack.h" #include "../Tokenizer/Tokenizer.h" #include "../SemiExp/SemiExp.h" /////////////////////////////////////////////////////////////// // ScopeStack element is application specific /* ToDo: * - chanage lineCount to two fields: lineCountStart and lineCountEnd */ struct element { std::string type; std::string name; size_t lineCount; std::string show() { std::ostringstream temp; temp << "("; temp << type; temp << ", "; temp << name; temp << ", "; temp << lineCount; temp << ")"; return temp.str(); } }; /////////////////////////////////////////////////////////////// // Repository instance is used to share resources // among all actions. /* * ToDo: * - add AST Node class * - provide field to hold root of AST * - provide interface to access AST * - provide helper functions to build AST, perhaps in Tree class */ class Repository // application specific { using FileSpec = std::string; using FileAssociations = std::unordered_map>; FileSpec _currentFile; ScopeStack stack; Scanner::Toker* p_Toker; FileAssociations _fileAssociations; static Repository* _pRepo; public: Repository(Scanner::Toker* pToker) { _pRepo = this; p_Toker = pToker; } static Repository* getInstance() { return _pRepo; } ScopeStack& scopeStack() { return stack; } Scanner::Toker* Toker() { return p_Toker; } size_t lineCount() { return (size_t)(p_Toker->currentLineCount()); } FileSpec& currentFile() { return _currentFile; } void setFileAssociation(const FileSpec& thisFile, const FileSpec& includeFile) { _fileAssociations[thisFile].push_back(includeFile); } FileAssociations& fileAssociations() { return _fileAssociations; } }; /////////////////////////////////////////////////////////////// // rule to detect #include class Includes : public IRule { public: bool doTest(ITokCollection*& pTc) { size_t pos = pTc->find("#"); if (pos < pTc->length()) { if ((*pTc)[pos + 1] == "include") doActions(pTc); } return true; } }; /////////////////////////////////////////////////////////////// // action to save include file class SaveAssociation : public IAction { Repository* p_Repos; public: SaveAssociation(Repository* pRepos) : p_Repos(pRepos) {} void doAction(ITokCollection*& pTc) { size_t fileSpecIndex = pTc->find("include") + 1; if ((*pTc)[fileSpecIndex] == "<") ++fileSpecIndex; p_Repos->setFileAssociation(p_Repos->currentFile(), (*pTc)[fileSpecIndex]); std::cout << "\n " << p_Repos->currentFile() << " includes " << (*pTc)[fileSpecIndex]; } }; #endif