From dc01d1682cbb736643ed294a92338dcddcd13ddd Mon Sep 17 00:00:00 2001 From: "Mike D. Lowis" Date: Sun, 2 Oct 2011 00:46:46 -0400 Subject: [PATCH] Initial commit --- README.txt | 5 +++ src/ast/ast.cpp | 69 +++++++++++++++++++++++++++++++++++++++++ src/ast/ast.h | 28 +++++++++++++++++ src/parser.cpp | 69 +++++++++++++++++++++++++++++++++++++++++ src/parser.h | 46 +++++++++++++++++++++++++++ src/visitor/visitor.cpp | 35 +++++++++++++++++++++ src/visitor/visitor.h | 30 ++++++++++++++++++ 7 files changed, 282 insertions(+) create mode 100644 README.txt create mode 100644 src/ast/ast.cpp create mode 100644 src/ast/ast.h create mode 100644 src/parser.cpp create mode 100644 src/parser.h create mode 100644 src/visitor/visitor.cpp create mode 100644 src/visitor/visitor.h diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..2b07464 --- /dev/null +++ b/README.txt @@ -0,0 +1,5 @@ +Overview +------------------------------------------------------------------------------- +This module provides a collection of C++ classes for implementing parsers in +C and C++. Among the classes provided are a homogenous abstract syntax tree +and an tree visitor. diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp new file mode 100644 index 0000000..8683e97 --- /dev/null +++ b/src/ast/ast.cpp @@ -0,0 +1,69 @@ +#include "ast.h" +#include +#include + +AST::AST(ASTNodeType type) +{ + node_type = type; + node_text = NULL; + node_children = new list(); +} + +AST::~AST() +{ + list::iterator it = node_children->begin(); + for(; it != node_children->end(); it++) + { + delete *(it); + } + delete node_children; + delete node_text; +} + +AST::AST(ASTNodeType type, char* text) +{ + node_type = type; + node_text = new string(text); + node_children = new list(); +} + +AST::AST(ASTNodeType type, int child_count, ...) +{ + va_list arg_list; + int i = 0; + node_type = type; + node_text = NULL; + node_children = new list(); + va_start (arg_list, child_count); + for (i = 0; i < child_count ; i++) + { + node_children->push_back( (AST*)va_arg(arg_list, AST*) ); + } + va_end(arg_list); +} + +ASTNodeType AST::type() +{ + return node_type; +} + +list* AST::children() +{ + return node_children; +} + +string AST::text() +{ + ostringstream oss; + if(node_text != NULL) + { + oss << node_text->c_str(); + } + return oss.str(); +} + +void AST::addChild(AST* node) +{ + node_children->push_back(node); +} + diff --git a/src/ast/ast.h b/src/ast/ast.h new file mode 100644 index 0000000..6877fdf --- /dev/null +++ b/src/ast/ast.h @@ -0,0 +1,28 @@ +#ifndef AST_H +#define AST_H + +#include +#include +#include + +using namespace std; + +typedef unsigned int ASTNodeType; + +class AST { + protected: + ASTNodeType node_type; + string* node_text; + list* node_children; + public: + AST(ASTNodeType type); + ~AST(); + AST(ASTNodeType type, char* text); + AST(ASTNodeType type, int child_count, ...); + ASTNodeType type(); + string text(); + list* children(); + void addChild(AST* node); +}; + +#endif diff --git a/src/parser.cpp b/src/parser.cpp new file mode 100644 index 0000000..84eb3f0 --- /dev/null +++ b/src/parser.cpp @@ -0,0 +1,69 @@ +/****************************************************************************** + * Copyright (C) 2001 Michael D. Lowis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ +/****************************************************************************** + * Includes and Prototypes + *****************************************************************************/ +#include +#include "parser.h" + +using namespace std; + +#ifdef PURE_PARSER +typedef void* yyscan_t; +extern int yyparse(ParseContext_T* context); +extern int yylex_init(yyscan_t* ptr_yy_globals); +extern void yyset_in (FILE* in_str , yyscan_t yyscanner); +#else +#endif + +/****************************************************************************** + * Public Functions + *****************************************************************************/ +Parser::~Parser() +{ + delete factory; +} + +void Parser::parseInput(FILE* in_file) +{ + if ( in_file != NULL ) + { + #ifdef PURE_PARSER + ParseContext_T context = { NULL, this}; + yylex_init( &(context.lexinfo) ); + yyset_in( in_file, context.lexinfo ); + yyparse( &context ); + #else + #endif + } +} + +void Parser::parseFile(string* in_file) +{ + FILE* input_file = fopen( in_file->c_str() ,"r"); + parseInput( input_file ); + delete in_file; +} + +void Parser::processAST(AST* root) +{ + Visitor* translator = factory->createVisitor(root); + translator->visit(); + cout << translator->str(); + delete translator; +} + diff --git a/src/parser.h b/src/parser.h new file mode 100644 index 0000000..b2e146c --- /dev/null +++ b/src/parser.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * Copyright (C) 2001 Michael D. Lowis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ +#ifndef PARSER_H +#define PARSER_H + +#include +#include "ast.h" +#include "visitor.h" + +using namespace std; + +class Parser { + protected: + VisitorFactory* factory; + private: + public: + Parser(VisitorFactory* trans_fact) : factory(trans_fact) {} + ~Parser(); + void parseFile(string* in_file); + void parseInput(FILE* in_file); + void processAST(AST* root); +}; + +#ifdef PURE_PARSER +typedef struct +{ + void* lexinfo; + Parser* parser; +} ParseContext_T; +#endif + +#endif diff --git a/src/visitor/visitor.cpp b/src/visitor/visitor.cpp new file mode 100644 index 0000000..71c3ccf --- /dev/null +++ b/src/visitor/visitor.cpp @@ -0,0 +1,35 @@ +#include "visitor.h" +#include + +using namespace std; + +void Visitor::visit(AST* cur, int depth) +{ + list* children; + list::iterator it; + + // If we are just starting then use the global tree + if(cur == NULL) cur = ast; + + // Execute or pre-walk actions + if(depth == 0) beforeVisit( cur, depth ); + + // Setup our locals + children = cur->children(); + it = children->begin(); + + // Visit the tree + beforeChildren(cur,depth); + depth++; + for(; it != children->end(); it++) + { + beforeChild( *it, depth ); + visit( *it, depth ); + afterChild( *it, depth ); + } + afterChildren(cur,depth); + + // Execute our post-walk actions + if(depth == 1) afterVisit( cur, depth ); +} + diff --git a/src/visitor/visitor.h b/src/visitor/visitor.h new file mode 100644 index 0000000..61fdde0 --- /dev/null +++ b/src/visitor/visitor.h @@ -0,0 +1,30 @@ +#ifndef TRANSLATOR_H +#define TRANSLATOR_H + +#include "ast.h" +#include +#include + +class Visitor { + protected: + AST* ast; + public: + Visitor(AST* tree) : ast(tree) {}; + ~Visitor() { delete ast; } + void visit(AST* cur = NULL, int depth = 0); + virtual string str() = 0; + private: + virtual void beforeVisit(AST* cur, int depth) = 0; + virtual void afterVisit(AST* cur, int depth) = 0; + virtual void beforeChildren(AST* cur, int depth) = 0; + virtual void afterChildren(AST* cur, int depth) = 0; + virtual void beforeChild(AST* cur, int depth) = 0; + virtual void afterChild(AST* cur, int depth) = 0; +}; + +class VisitorFactory { + public: + virtual Visitor* createVisitor(AST* root) = 0; +}; + +#endif -- 2.54.0