Project #2 Sample - Rule-based Parser

Version 1.0,
Due Date: Already Completed - find code here
Note:
This is a demonstration project, which you are not expected to implement.
Instead, you will implement the projects linked on the Synchronous pages.

Purpose:

This second project will build on the packages developed in Sample Project #1, e.g., the tokenizer and semi-expression packages. In this project we build a rule-based parser suitable for analyzing C++ source code. You will find it useful to read the Parser Blog, before starting work on this project.
Parsing is a process of analyzing parts of some, perhaps large and complex entity. We will be analyzing C++ source code structure - classes and unbound functions - and metrics for those parts, e.g., function sizes and complexities1.
Our parser will hold a collection of rules, derived from an IRule interface. The parser will have a parse() function that extracts a semi-expression from the lexical scanner and passes it to each rule. The parser doesn't need to know what the rule does with its input, but each rule will return a boolean value that indicates whether the semi-expression should be passed on to subsequent rules.
Each rule has a collection of one or more actions that derive from the IAction interface. When a rule discovers that its semi-expression satisfies its conditions, it then invokes each of its actions.
Actions may simply display some property of the semi-expression, or may add information from the semi-expression to data structures in a Repository.

Requirements:

Your Parser Project:
  1. Shall be written in C++, using the standard C++ libraries. You may also use helper code provided in the course Repository.
  2. Shall use Visual Studio, Community Edition available at no cost.
  3. Shall define a Parser class and IRule and IAction interfaces.
  4. Shall provide derived rules for detecting begining and end of an arbitry scope2, beginning of namespace, class, struct, and function scopes.
  5. Shall provide derived actions that display a program-ordered list of the grammatical constructs identified in the previous requirement.

  1. We define the complexity of a function as the number of scopes contained in the function plus the scope of the function. Note that this counts all the descendent scopes, not just the child scopes of the function.
  2. Scopes are defined by braces: '{' and '}'.

What you need to know:

In order to successfully meet these requirements you will need to know:
  1. How to define a C++ interface - a struct with no member data or constructors, and all pure virtual function declarations, except for a virtual destructor with an empty body.
  2. How to use inheritance and some of the simpler STL containers.