diff options
Diffstat (limited to 'src/uscxml/plugins/datamodel/c89/C89Parser.cpp')
-rw-r--r-- | src/uscxml/plugins/datamodel/c89/C89Parser.cpp | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/src/uscxml/plugins/datamodel/c89/C89Parser.cpp b/src/uscxml/plugins/datamodel/c89/C89Parser.cpp new file mode 100644 index 0000000..540db37 --- /dev/null +++ b/src/uscxml/plugins/datamodel/c89/C89Parser.cpp @@ -0,0 +1,284 @@ +/** + * @file + * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * 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. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#include "C89Parser.h" +#include "parser/c89.tab.hpp" +#include "uscxml/messages/Event.h" + +#include <iostream> +#include <cassert> + +struct yy_buffer_state; +typedef yy_buffer_state *YY_BUFFER_STATE; +extern YY_BUFFER_STATE c89__scan_buffer(char *, size_t, void*); +void c89__delete_buffer(YY_BUFFER_STATE, void*); +YY_BUFFER_STATE c89__scan_string (const char * yystr , void*); + + +extern int c89_lex (C89_STYPE* yylval_param, C89_LTYPE* yylloc_param, void* yyscanner); +int c89_lex_init (void**); +int c89_lex_destroy (void*); + +void c89_error (void* yylloc_param, uscxml::C89Parser* ctx, void* yyscanner, const char* err) { + C89_LTYPE* yylloc = (C89_LTYPE*)yylloc_param; + // mark as pending exception as we cannot throw from constructor and have the destructor called + ERROR_EXECUTION(excEvent, err); + excEvent.data.compound["line"] = uscxml::Data(yylloc->first_line, uscxml::Data::VERBATIM); + excEvent.data.compound["col"] = uscxml::Data(yylloc->first_column, uscxml::Data::VERBATIM); + + std::stringstream ssUnderline; + for (size_t i = 0; i < yylloc->first_column; i++) + ssUnderline << " "; + ssUnderline << "^"; + excEvent.data.compound["sourcemark"] = uscxml::Data(ssUnderline.str(), uscxml::Data::VERBATIM); + + ctx->pendingException = excEvent; +} + +namespace uscxml { + +C89Parser::C89Parser(const std::string& expr) { + init(expr); +} + +C89Parser::C89Parser(const std::string& expr, int nrArgs, ...) { + init(expr); + + if (nrArgs == 0) + return; + + std::stringstream errSS; + std::string seperator; + errSS << "C89 syntax type mismatch: Expected {"; + + va_list ap; + va_start(ap, nrArgs); + for(int i = 1; i <= nrArgs; i++) { + int expectedType = va_arg(ap, int); + if (type == expectedType) + return; + errSS << seperator << typeToDesc(expectedType); + seperator = ", "; + } + errSS << "} but got " << typeToDesc(type); + ERROR_EXECUTION_THROW(errSS.str()); +} + +void C89Parser::init(const std::string& expr) { + ast = NULL; + parseInCompound = 0; + input_length = expr.length() + 2; // plus some zero terminators + input = (char*) calloc(1, input_length); + memcpy(input, expr.c_str(), expr.length()); + + c89_lex_init(&scanner); + // c89_assign_set_extra(ast, &scanner); + buffer = c89__scan_string(input, scanner); + // buffer = c89__scan_buffer(input, input_length, scanner); + c89_parse(this, scanner); + if (pendingException.name.size() > 0) { + // parsing failed in c89_error + destroy(); + pendingException.data.compound["sourceline"] = Data(expr, Data::VERBATIM); + throw pendingException; + } +} + +void C89Parser::destroy() { + if (ast) + delete(ast); + free(input); + c89__delete_buffer((YY_BUFFER_STATE)buffer, scanner); + c89_lex_destroy(scanner); +} + +C89Parser::~C89Parser() { + destroy(); +} + +std::string C89Parser::typeToDesc(int type) { + return ""; +} + +C89ParserNode::~C89ParserNode() { + while(operands.size() > 0) { + delete operands.front(); + operands.pop_front(); + } + if (loc) + free(loc); +} + +C89ParserNode* C89Parser::node(int type, int nrArgs, ...) { + C89ParserNode* newNode = new C89ParserNode(); + + newNode->type = type; + va_list ap; + va_start(ap, nrArgs); + for(int i = 1; i <= nrArgs; i++) { + C89ParserNode* op = va_arg(ap, C89ParserNode*); + assert(op != NULL); + + newNode->operands.push_back(op); + newNode->operands.back()->parent = newNode; + } + + this->ast = newNode; + return newNode; +} + +C89ParserNode* C89Parser::value(int type, void* location, const char* value) { + C89ParserNode* newNode = new C89ParserNode(); + + if (location) { + C89_LTYPE* location_param = (C89_LTYPE*)location; + newNode->loc = (C89ParserNode::Location*)malloc(sizeof(C89ParserNode::Location)); + newNode->loc->firstCol = location_param->first_column; + newNode->loc->firstLine = location_param->first_line; + newNode->loc->lastCol = location_param->last_column; + newNode->loc->lastLine = location_param->last_line; + } + + if (value != NULL) { + newNode->value = value; + } + newNode->type = type; + this->ast = newNode; + return newNode; +} + + +void C89Parser::dump() { + switch (type) { + case C89_EXPR: + std::cout << "C89 Expression" << std::endl; + break; + case C89_DECL: + std::cout << "C89 Declarations" << std::endl; + break; + case C89_STMNT: + std::cout << "C89 Statement" << std::endl; + break; + } + ast->dump(); +} + + +void C89ParserNode::merge(C89ParserNode* node) { + for (std::list<C89ParserNode*>::iterator iter = node->operands.begin(); + iter != node->operands.end(); iter++) { + operands.push_back(*iter); + (*iter)->parent = this; + } + node->operands.clear(); +} + +void C89ParserNode::push(C89ParserNode* node) { + node->parent = this; + operands.push_back(node); +} + +void C89ParserNode::dump(int indent) { + std::string padding; + for (size_t i = 0; i < indent; i++) { + padding += " "; + } + std::cout << padding << typeToDesc(type) << ": " << value; + if (loc != NULL) { + std::cout << " (" << loc->firstLine << ":" << loc->firstCol << ")-(" << loc->lastLine << ":" << loc->lastCol << ")"; + } + std::cout << std::endl; + for (std::list<C89ParserNode*>::iterator iter = operands.begin(); + iter != operands.end(); iter++) { + (*iter)->dump(indent + 1); + } +} + +std::string C89ParserNode::typeToDesc(int type) { + if (type < 256) { + return std::string((char*)(&type), 1); + } + + switch(type) { + + case IDENTIFIER: return "IDENTIFIER"; + case CONSTANT: return "CONSTANT"; + case STRING_LITERAL: return "STRING_LITERAL"; + case SIZEOF: return "SIZEOF"; + case PTR_OP: return "PTR_OP"; + case INC_OP: return "INC_OP"; + case DEC_OP: return "DEC_OP"; + case LEFT_OP: return "LEFT_OP"; + case RIGHT_OP: return "RIGHT_OP"; + case LE_OP: return "LE_OP"; + case GE_OP: return "GE_OP"; + case EQ_OP: return "EQ_OP"; + case NE_OP: return "NE_OP"; + case AND_OP: return "AND_OP"; + case OR_OP: return "OR_OP"; + case MUL_ASSIGN: return "MUL_ASSIGN"; + case DIV_ASSIGN: return "DIV_ASSIGN"; + case MOD_ASSIGN: return "MOD_ASSIGN"; + case ADD_ASSIGN: return "ADD_ASSIGN"; + case SUB_ASSIGN: return "SUB_ASSIGN"; + case LEFT_ASSIGN: return "LEFT_ASSIGN"; + case RIGHT_ASSIGN: return "RIGHT_ASSIGN"; + case AND_ASSIGN: return "AND_ASSIGN"; + case XOR_ASSIGN: return "XOR_ASSIGN"; + case OR_ASSIGN: return "OR_ASSIGN"; + case TYPE_NAME: return "TYPE_NAME"; + case TYPEDEF: return "TYPEDEF"; + case EXTERN: return "EXTERN"; + case STATIC: return "STATIC"; + case AUTO: return "AUTO"; + case REGISTER: return "REGISTER"; + case CHAR: return "CHAR"; + case SHORT: return "SHORT"; + case INT: return "INT"; + case LONG: return "LONG"; + case SIGNED: return "SIGNED"; + case UNSIGNED: return "UNSIGNED"; + case FLOAT: return "FLOAT"; + case DOUBLE: return "DOUBLE"; + case CONST: return "CONST"; + case VOLATILE: return "VOLATILE"; + case VOID: return "VOID"; + case STRUCT: return "STRUCT"; + case UNION: return "UNION"; + case ENUM: return "ENUM"; + case ELLIPSIS: return "ELLIPSIS"; + case CASE: return "CASE"; + case DEFAULT: return "DEFAULT"; + case IF: return "IF"; + case ELSE: return "ELSE"; + case SWITCH: return "SWITCH"; + case WHILE: return "WHILE"; + case DO: return "DO"; + case FOR: return "FOR"; + case GOTO: return "GOTO"; + case CONTINUE: return "CONTINUE"; + case BREAK: return "BREAK"; + case RETURN: return "RETURN"; + + default: + return std::string("UNK(") + toStr(type) + ")"; + } +} + +}
\ No newline at end of file |