I have a struct that looks like this:
// A lexical scope that keeps track of every declared variable
// in a function
struct LexState
{
// A map containing the index of a variable in it's function
// The key is the variable name
std::unordered_map<std::string, int> _vars;
Function *_function;
LexState *_parent;
};
This is the code using the struct:
#define DD(msg) std::cout << "Debug: " << msg << '\n'
#define DD1(msg, p1) std::cout << "Debug: " << msg << p1 << '\n'
#define DD2(msg, p1, p2) std::cout << "Debug: " << msg << p1 << p2 << '\n'
// A lexical scope that keeps track of every declared variable
// in a function
struct LexState
{
// A map containing the index of a variable in it's function
// The key is the variable name
std::unordered_map<std::string, int> _vars;
Function *_function;
LexState *_parent;
LexState(LexState *parent, Function *function)
{
_parent = parent;
_function = function;
}
Value *SearchVar(char *name)
{
if (_parent == nullptr)
{
return nullptr;
}
std::string str(name);
auto var = _parent->_vars.find(str);
if (var == _parent->_vars.end())
{
return _parent->SearchVar(name);
}
return _function->GetLocalVar(var->second)->GetValue();
}
};
class Compiler
{
public:
State *_state;
Function *_current_function;
GC *_gc;
LexState *_ls;
Compiler(State *state) :
_state(state)
{
_current_function = nullptr;
_gc = state->GetGC();
_current_function = new Function(nullptr);
_state->_main_function = _current_function;
_ls = nullptr;
}
void PushFunction()
{
Function *new_function = new Function(_current_function);
_current_function = new_function;
LexState *new_ls = new LexState(_ls, new_function);
// even now, right after creating new_ls, new_ls->_vars is 0
printf("%p\n", &new_ls->_vars);
_ls = new_ls;
}
void PopFunction()
{
_current_function = _current_function->_parent;
LexState *parent = _ls->_parent;
delete _ls;
_ls = parent;
}
int DeclareVar(const Symbol *node)
{
assert(node->_type == NODE_SYMBOL);
DD("Declaring variable");
auto token = node->_token;
char name[token->len + 1];
memcpy(name, token->pos, token->len);
name[token->len] = '\0';
int idx = _current_function->AddLocalVar(name);
std::string key(name);
printf("%p\n", &_ls->_vars);
if (_ls != nullptr)
_ls->_vars.insert(std::make_pair(key, idx));
else
DD("LexState nullptr");
DD("Variable declared");
return idx;
}
void Compile(const Node *node)
{
switch (node->_type)
{
case NODE_CHUNK:
CompileChunk((Chunk *)node);
break;
case NODE_BLOCK:
CompileBlock((Block *)node);
break;
case NODE_FUNCTION_DEF:
CompileFunctionDef((FunctionDef *)node);
break;
case NODE_CONDITIONAL:
CompileConditional((ConditionalStatement *)node);
break;
case NODE_BINARY_EXPR:
CompileBinaryExpr((BinaryExpr *)node);
break;
case NODE_UNARY_EXPR:
CompileUnaryExpr((UnaryExpr *)node);
break;
case NODE_SYMBOL:
CompileSymbol((Symbol *)node);
break;
case NODE_STRING_LITERAL:
CompileStringLiteral((StringLiteral *)node);
break;
case NODE_BOOL_LITERAL:
CompileBoolLiteral((BoolLiteral *)node);
break;
case NODE_INT_LITERAL:
CompileIntLiteral((IntLiteral *)node);
break;
}
}
void CompileChunk(const Chunk *chunk)
{
Compile(chunk->_block);
AddCode(OP_HALT);
}
void CompileBlock(const Block *block)
{
std::vector<Node *> vec = block->_vec;
for (auto it = vec.begin(); it != vec.end(); it++)
{
Compile(*it);
}
}
void CompileFunctionDef(const FunctionDef *func)
{
Value v;
int f = AddConstant(v);
AddCode(OP_PUSH, f);
Value *vp = _current_function->GetConstant(f);
if (func->_name)
{
int fvar = DeclareVar((Symbol *)func->_name);
AddCode(OP_STOR_LOCAL, fvar);
}
ArgList *argsnode = (ArgList *)func->_args;
auto args = argsnode->_vec;
int argcount = args.size();
PushFunction();
auto closure = new Closure(_current_function);
closure->_argcount = argcount;
std::cout << argcount << '\n';
vp->_closure = closure;
vp->_type = VALUE_CLOSURE;
// Compiling inside function
// Arguments are compiled in reserved order, because in the function call
// the passed arguments will be pushed in the order they are passed
for (auto it = args.rbegin(); it != args.rend(); it++)
{
int var = DeclareVar((Symbol *)*it);
AddCode(OP_STOR_LOCAL, var);
}
if (func->_guard)
{
Compile(func->_guard);
}
else
{
Compile(func->_body);
}
AddCode(OP_RETURN);
// End function
PopFunction();
}
void CompileConditional(const ConditionalStatement *node)
{
auto function = _current_function;
Compile(node->_condition);
int cond_res_idx = function->AddLocalVar();
AddCode(OP_DUP);
// Store the condition result into an internal variable
AddCode(OP_STOR_LOCAL, cond_res_idx);
AddCode(OP_DUP);
int true_jmp = AddCode(OP_JMP_T, 0);
int false_jmp = AddCode(OP_JMP_F, 0);
// Save index of the first code of the block
int block_idx = function->_code.size();
// Jump to block when condition is true
function->ChangeCode(true_jmp, block_idx);
Compile(node->_expr1);
AddCode(OP_PUSH_LOCAL, cond_res_idx);
// Jump to the end of the whole if-elif-else statement
// if the condition result was true
int exit_jmp = AddCode(OP_JMP_T, 0);
// Save index of the first code after this statement
int right_idx = function->_code.size();
function->ChangeCode(false_jmp, right_idx);
if (node->_expr2 != nullptr)
{
Compile(node->_expr2);
}
else
{
AddCode(OP_PUSH_NIL);
}
int end_idx = function->_code.size();
function->ChangeCode(exit_jmp, end_idx);
}
void CompileBinaryExpr(const BinaryExpr *expr)
{
auto function = _current_function;
auto token = expr->_op->type;
if (token == TOKEN_ASSIGN)
{
if (expr->_left->_type == NODE_SYMBOL)
{
int var = DeclareVar((Symbol *)expr->_left);
Compile(expr->_right);
AddCode(OP_STOR_LOCAL, var);
return;
}
}
// A function call
if (token == TOKEN_LEFTPAREN)
{
ArgList *arglist = (ArgList *)expr->_right;
auto args = arglist->_vec;
int argcount = args.size();
// A function call cannot have more than 255 arguments
assert(argcount < 256);
for (auto it = args.begin(), end = args.end();
it != end; it++)
{
Compile(*it);
}
Compile(expr->_left);
AddCode(OP_CALL, argcount);
return;
}
Compile(expr->_left);
// Both 'and' and 'or' expressions does short circuit
if (token == TOKEN_BOOL_AND ||
token == TOKEN_BOOL_OR)
{
AddCode(OP_DUP);
OpType op = (token == TOKEN_BOOL_AND) ? OP_JMP_F : OP_JMP_T;
int idx = AddCode(op, function->_ip + 1);
Compile(expr->_right);
int next = function->_code.size();
uint32_t instr = function->_code[idx];
function->ChangeCode(idx, next);
return;
}
// No need for lazy evaluation, compile normally
Compile(expr->_right);
switch (expr->_op->type)
{
case TOKEN_ADD:
AddCode(OP_ADD);
break;
case TOKEN_SUB:
AddCode(OP_SUB);
break;
case TOKEN_MUL:
AddCode(OP_MUL);
break;
case TOKEN_DIV:
AddCode(OP_DIV);
break;
case TOKEN_POW:
AddCode(OP_POW);
break;
case TOKEN_AND:
AddCode(OP_AND);
break;
case TOKEN_OR:
AddCode(OP_OR);
break;
case TOKEN_XOR:
AddCode(OP_XOR);
break;
case TOKEN_LT:
AddCode(OP_LT);
break;
case TOKEN_GT:
AddCode(OP_GT);
break;
case TOKEN_LTEQ:
AddCode(OP_LTEQ);
break;
case TOKEN_GTEQ:
AddCode(OP_GTEQ);
break;
case TOKEN_SHIFT_L:
AddCode(OP_SHIFT_L);
break;
case TOKEN_SHIFT_R:
AddCode(OP_SHIFT_R);
break;
}
}
void CompileUnaryExpr(const UnaryExpr *expr)
{
Compile(expr->_right);
switch (expr->_token->type)
{
case TOKEN_SUB:
AddCode(OP_NEGATE);
break;
case TOKEN_NOT:
AddCode(OP_NOT);
break;
case TOKEN_BOOL_NOT:
AddCode(OP_BOOL_NOT);
break;
}
}
// This function gets called only when it's a reference
void CompileSymbol(const Symbol *node)
{
auto token = node->_token;
char name[token->len + 1];
memcpy(name, token->pos, token->len);
name[token->len] = '\0';
DD1("Searching reference: ", name);
Value *upvalue = _ls->SearchVar(name);
if (upvalue)
{
int idx = _current_function->AddUpValue(upvalue);
AddCode(OP_PUSH_UPVALUE, idx);
return;
}
int idx = _current_function->GetLocalVarIndex(name);
AddCode(OP_PUSH_LOCAL, idx);
}
void CompileStringLiteral(const StringLiteral *sl)
{
Value v(sl->_token->str, sl->_token->len);
AddCode(OP_PUSH, AddConstant(v));
}
void CompileBoolLiteral(const BoolLiteral *bl)
{
Value v(bl->_token->type == TOKEN_TRUE);
AddCode(OP_PUSH, AddConstant(v));
}
void CompileIntLiteral(const IntLiteral *il)
{
Value v(il->_token->num);
AddCode(OP_PUSH, AddConstant(v));
}
int AddCode(OpType code)
{
return _current_function->AddCode(code);
}
int AddCode(OpType code, int a)
{
return _current_function->AddCode(code, a);
}
int AddConstant(const Value &v)
{
return _current_function->AddConstant(v);
}
};
The program outputs:
Declaring variable
0
It crashes before the DD("Variable declared") part.
Even though i'm new to C++, I'm pretty sure I don't need to allocate the unordered map myself, right? As it's not a pointer, it will be allocated when I do new LexState
So is there any initialization/allocation I am forgetting?
%i is not the right format specifier to use to print a pointer. You are most likely getting the output that represents a truncated value of the pointer. Use %p instead.
printf("%p\n", &state->_vars);
I don't see anything wrong using state->_vars. See working code at http://ideone.com/YAJK5K.
Related
template <class T>
struct stkNode
{
BinTreeNode<T> *ptr;
enum tag {R,L}tag;
stkNode(BinTreeNode<T> *N = NULL) : ptr(N),tag(L){}
};
template<class T>
void BinaryTree<T>::PostOrder(void(*visit)(BinTreeNode<T> *p))
{
SeqStack<stkNode<T> > S;
stkNode<T> w;
BinTreeNode<T> *p = root;
do
{
while (p != NULL)
{
w.ptr = p;
w.tag = w.L;
S.Push(w);
p = p->leftChild;
}
bool continuel = true;
while (!S.IsEmpty() && continuel)
{
S.Pop(w);
p = w.ptr;
switch (w.tag)
{
case w.L: //---------------this line--------------------------
w.tag = w.R;
S.Push(w);
continuel = false;
p = p->rightChild;
break;
case w.R: // -----------and this line-------------
visit(p);
break;
}
}
} while (!S.IsEmpty());
}
When i compile it on Devc++, it will be an error looks like:
[Error] '.' cannot appear in a constant-expression.
But when i compile it on Visual Studio 2015,the error will not happen.
Why??????
-----------update my problem--------------------
such as
#include <iostream>
using namespace std;
struct exp
{
char ch;
enum dir{
L,R
}direction;
exp(char name,dir d){
ch = name;
direction = d;
}
};
int main()
{
exp t('a',exp.L); //this line
return 0;
}
it was the same
The problem is that i access method of enum wrongly....
The right Code is:
template<class T>
void BinaryTree<T>::PostOrder(void(*visit)(BinTreeNode<T> *p))
{
SeqStack<stkNode<T> > S;
stkNode<T> w;
BinTreeNode<T> *p = root;
do
{
while (p != NULL)
{
w.ptr = p;
w.tag = w.L;
S.Push(w);
p = p->leftChild;
}
bool continuel = true;
while (!S.IsEmpty() && continuel)
{
S.Pop(w);
p = w.ptr;
switch (w.Tag)
{
case stkNode<T>::L:
w.tag = w.R;
S.Push(w);
continuel = false;
p = p->rightChild;
break;
case stkNode<T>::R:
visit(p);
break;
}
}
} while (!S.IsEmpty());
}
I'm trying to write a simple script system (for a video game) on which there's no huge complexity tasks, but simple boolean checks & action sets.
I'm a student, but I'm not studying programming, I just do it as a hobby, so I'm learning the basics and recently I felt to write my own parser & interpreter,
but since this is my first approach of AST I do not understand why the result keeps being true instead of false (for the given expressions), also would like to know if it's the best approach for what I am looking for.
You can compile with my source files just fine.
Expression.h
#pragma once
enum OperatorType
{
OPERATOR_EQUALS = 0, // =
OPERATOR_LESSER_THAN, // <
OPERATOR_GREATER_THAN, // >
OPERATOR_LESSER_OR_EQUALS, // <=
OPERATOR_GREATER_OR_EQUALS, // >=
OPERATOR_UNEQUAL, // <>
OPERATOR_MULTIPLY, // *
OPERATOR_SUM, // +
OPERATOR_SUB, // -
};
class Expression;
class ATSVisitor;
class ATSNode
{
public:
virtual void accept(ATSVisitor* visitor) = 0;
};
class ATSRoot
{
public:
Expression* expression;
};
class Expression : public ATSNode
{
public:
~Expression()
{
left = nullptr;
right = nullptr;
}
virtual void accept(ATSVisitor* visitor) = 0;
Expression* left;
Expression* right;
};
class OperationExpression : public Expression
{
public:
OperationExpression() : Expression(){}
virtual void accept(ATSVisitor* visitor);
OperatorType type;
};
class NumberExpression : public Expression
{
public:
NumberExpression() : Expression(){ value = 0; }
virtual void accept(ATSVisitor* visitor);
int value;
};
class ATSVisitor
{
public:
ATSVisitor()
{
Result = false;
}
bool evaluate(ATSRoot* root);
void visit(OperationExpression* expression);
void visit(NumberExpression* expression);
bool Result;
int number;
};
Expression.cpp
#include "expressions.h"
#include <iostream>
void OperationExpression::accept(ATSVisitor* visitor)
{
visitor->visit(this);
}
void NumberExpression::accept(ATSVisitor* visitor)
{
visitor->visit(this);
}
bool ATSVisitor::evaluate(ATSRoot* root)
{
std::cout << "Evaluating ROOT" << std::endl;
bool result = false;
root->expression->accept(this);
result = Result;
return result;
}
void ATSVisitor::visit(OperationExpression* expression)
{
std::cout << "Visitor just visited OPERATIONEXPRESSION: " << expression->type << std::endl;
expression->left->accept(this);
int leftValue = number;
expression->right->accept(this);
int rightValue = number;
switch (expression->type)
{
case OPERATOR_EQUALS:
Result = leftValue == rightValue;
case OPERATOR_GREATER_OR_EQUALS:
Result = leftValue >= rightValue;
case OPERATOR_GREATER_THAN:
Result = leftValue > rightValue;
case OPERATOR_LESSER_OR_EQUALS:
Result = leftValue <= rightValue;
case OPERATOR_LESSER_THAN:
Result = leftValue < rightValue;
case OPERATOR_MULTIPLY:
Result = leftValue * rightValue;
case OPERATOR_SUB:
Result = leftValue - rightValue;
case OPERATOR_SUM:
Result = leftValue + rightValue;
case OPERATOR_UNEQUAL:
Result = leftValue != rightValue;
}
}
void ATSVisitor::visit(NumberExpression* expression)
{
std::cout << "Visitor just visited NUMBEREXPRESSION: " << expression->value << std::endl;
number = expression->value;
}
Main.cpp
#include <iostream>
#include "expressions.h"
int main(int argc, char** argv)
{
ATSVisitor* visitor = new ATSVisitor();
// QuestValue(100)>=10
ATSRoot* root = new ATSRoot();
OperationExpression* operation = new OperationExpression();
operation->type = OPERATOR_GREATER_OR_EQUALS;
NumberExpression* number1 = new NumberExpression();
number1->value = 1;
NumberExpression* number2 = new NumberExpression();
number2->value = 10;
operation->left = number1;
operation->right = number2;
root->expression = operation;
if (!visitor->evaluate(root))
{
std::cout << "\nOperation evaluation FAILED!" << std::endl;
}
else
{
std::cout << "\nOperation evaluation SUCCEED!" << std::endl;
}
std::cout << "Finished" << std::endl;
std::cin.get();
delete root;
delete number1;
delete number2;
delete operation;
return EXIT_SUCCESS;
}
Basically this AST with Visitor pattern is supposed to parse if when my tokenizer parses this script:
1>=10
Will return if it succeeded or not
Your switch statement doesn't do what you think it does.
In C++, as in C, executing a switch statement causes control flow to jump to the appropriate case label. It then executes the remainder of the block, which means that it executes the following case label, and the one following that, unless it hits a break statement.
Needless to say, the normal style is to end every case section with break:
switch (expression->type)
{
case OPERATOR_EQUALS:
Result = leftValue == rightValue;
break;
case OPERATOR_GREATER_OR_EQUALS:
Result = leftValue >= rightValue;
break;
case OPERATOR_GREATER_THAN:
Result = leftValue > rightValue;
break;
case OPERATOR_LESSER_OR_EQUALS:
Result = leftValue <= rightValue;
break;
case OPERATOR_LESSER_THAN:
Result = leftValue < rightValue;
break;
case OPERATOR_MULTIPLY:
Result = leftValue * rightValue;
break;
case OPERATOR_SUB:
Result = leftValue - rightValue;
break;
case OPERATOR_SUM:
Result = leftValue + rightValue;
break;
case OPERATOR_UNEQUAL:
Result = leftValue != rightValue;
break;
}
Otherwise, regardless of what expression->type evaluates to (as long as it evaluates to one of the label expressions), it will eventually execute the final statement, Result = leftValue != rightValue;.
I am currently learning how to implement a binary search tree, but using a more rudimentary C approach(please no "use classes now"). However, there is a big problem with dynamic memory getting itself deleted. The head value gets updated correctly, however, every other point gets itself deleted. Can anyone help me? Also, it would be nice if you would offer some tips how to tighten up my implementation of the tree. A basic rundown of the program: you input a character and thus you run one of the tree's functions. Mind though, that this implementation is a pure BST, so no balancing. Thank you.
#include <iostream>
struct point{
point* parent, *left, *right;
int val = -1;
};
point* biggest;
point empty;
point search(int pos, bool near, point* loc = biggest){
if(loc->val == pos){
return *loc;
} else if(loc->left->val != -1 and loc->val > pos){
return search(pos, near, loc->left);
} else if(loc->right->val != -1){
return search(pos, near, loc->right);
}
if(near){
return *loc;
} else{
point fail;
return fail;
}
}
void insert(int pos, point* res){
point loc = search(pos, true);
res->val = pos, res->left = &empty, res->right = &empty, res->parent = &loc;
if(loc.val < res->val){
loc.left = res;
} else{
loc.right = res;
}
}
void remove(int pos){
}
int pred(int pos){
point res = search(pos, false);
if(res.val == -1){
return -1;
}
}
int succ(int pos){
point res = search(pos, false);
if(res.val == -1){
return -1;
}
}
void inorder(point* pos = biggest){
if(pos->left->val != -1){
inorder(pos->left);
}
std::cout << pos->val << " ";
if(pos->right->val != -1){
inorder(pos->right);
}
}
int main() {
point start;
start.parent = &empty, start.left = &empty, start.right = ∅
biggest = &start;
char c;
int pos;
do{
std::cin >> c >> pos;
switch (c){
case 'S':
std::cout << search(pos, false).val << std::endl;
break;
case 'I':
if(biggest->val == -1){
start.val = pos;
} else{
point* res = new point;
insert(pos, res);
}
break;
case 'R':
remove(pos);
break;
case 'P':
std::cout << pred(pos) << std::endl;
break;
case 'N':
std::cout << succ(pos) << std::endl;
break;
case 'O':
inorder();
std::cout << std::endl;
break;
}
} while(c != '0');
return 0;
}
Apart from much weirdness in your code I would say that here :
void insert(int pos, point* res){
point loc = search(pos, true);
res->val = pos, res->left = &empty, res->right = ∅
res->parent = &loc; // <=== here
you modify res->parent to point at a local variable loc. After the insert() function returns the point loc does not exist anymore.
Also you are already using classes; C++ structs and classes are pretty much identical ... apart from the default member visibility.
I have a class with a method that should return a vector of strings. the getCommVector method has to push_back the elements of a string array into a string vector that can then be returned by the method. When trying to add a string element to the string vector i get:
libc++abi.dylib: terminate called throwing an exception
2Program ended with exit code: 0
I cannot understand why I can't push_back strings to the vector. Any ideas?
Thanks in advance!
code segments of interest (edited after suggestions):
class Command {
public:
//Command (std::string, bool, bool);
void setOperators(std::string,bool, bool);
void analyseCommand();
Command();
std::vector<std::string> getCommVector ();
private:
int numOperators; //number of total commands
int opCount; //current command number
std::string input_string;
bool field_command, byte_command;
std::string commVector[3];
std::vector<std::string> finalCommVector;
void byte_analysis();
void field_analysis();
void decode_command();
void syntax_error();
void decode_error();
};
Command::Command() : numOperators(0), opCount(0), field_command(false),byte_command(false)
{
}
std::vector<std::string> Command::getCommVector ()
{
std::string s ="test";
finalCommVector.push_back("s");
return finalCommVector;
}
adding SSCE:
class Command {
public:
//Command (std::string, bool, bool);
void setOperators(std::string,bool, bool);
void analyseCommand();
Command();
std::vector<std::string> getCommVector ();
private:
int numOperators; //number of total commands
int opCount; //current command number
std::string input_string;
bool field_command, byte_command;
std::string commVector[3];
std::vector<std::string> finalCommVector;
void byte_analysis();
void field_analysis();
void decode_command();
void syntax_error();
void decode_error();
};
Command::Command() : numOperators(0), opCount(0), field_command(false),byte_command(false)
{
}
void Command::syntax_error()
{
std::cout<<"Incorrect Syntax Error: Usage: linuxcut -b num -f num \n";
exit(EXIT_FAILURE);
}
void Command::decode_error()
{
std::cout<<"Decode Error: Usage: linuxcut -b num -f num \n";
exit(EXIT_FAILURE);
}
void Command::analyseCommand()
{
if (byte_command) {
//start byte command analysys
byte_analysis();
}
else if (field_command)
{
//start field command analysys
field_analysis();
}
}
void Command::setOperators(std::string input_argument, bool is_field, bool is_byte)
{
input_string = input_argument;
field_command = is_field;
byte_command = is_byte;
}
std::vector<std::string> Command::getCommVector ()
{
std::string s = "ssd";
finalCommVector.push_back(s);
/*
for (int i = 0; i<sizeof(commVector); i++)
{
if (commVector[i] != "")
{
//debug
std::cout<<"asdas";
}
}
*/
return finalCommVector;
}
void Command::byte_analysis()
{
int next_state = 0;
int dashCount = 0;
int commVectIndex = 0;
//iterate through string and check if the argument is valid
for (int i= 0; i<input_string.length(); i++) {
switch (next_state) {
case 0: //start
//if character is a number:
if (isdigit(input_string.at(i)))
{
//first elemnt of command commVector is number
commVector[commVectIndex]+=input_string.at(i);
//DEBUG
std::cout<<commVector[commVectIndex];
next_state = 1;
}
//if character is a dash:
else if (input_string[i] == '-')
{
//increment dashCount
dashCount++;
//if next character in input_string is a number continue
if (isdigit(input_string[i+1])) {
commVector[commVectIndex]+=input_string.at(i);
commVectIndex++;
next_state = 1;
}
else //else error
{
syntax_error();
}
}
//if it's niether: error!
else
{
syntax_error();
}
break;
case 1:
//if next character is a number:
if (isdigit(input_string[i]))
{
commVector[commVectIndex]+=input_string.at(i);
next_state = 1;
}
//if next character is dash
else if (input_string[i] == '-'&& dashCount <= 3)
{
dashCount++;
//increment commandVectIndex
commVectIndex++;
next_state = 2;
commVector[commVectIndex]+=input_string.at(i);
//increment commandVectIndex to accomodate next operation
commVectIndex++;
}
//if it's niether: error!
else
{
syntax_error();
}
break;
case 2://previous character was dash
//if next character is number
if (isdigit(input_string[i]))
{
commVector[commVectIndex]+=input_string.at(i);
next_state = 1;
}
//if it's niether: error!
else
{
syntax_error();
}
break;
default:
syntax_error();
break;
}
}
}
void Command::field_analysis()
{
}
/*****************FUNCTIONS DEFINITIONS***************/
void print_usage() {
std::cout<<"Incorrect Syntax Error: Usage: linuxcut -b num -f num \n";
}
/*****************END OF FUNCTIONS DEFINITIONS***************/
/***************** MAIN ***************/
int main(int argc, char *argv[]) {
int opt= 0;
std::string byte = "-1-2,2",field = "";
std::string sub_arg_delimiter = ","; //delimiter for comma serparated arguments
static bool complement = false;
int diffOpt = 0; //stores the difference between optind and argc to read filenames in command
std::string fileName;
//Specifying the expected options
//The two options l and b expect numbers as argument
static struct option long_options[] = {
{"byte", required_argument, 0, 'b' },
{"field", required_argument, 0, 'f' },
{"complement", no_argument, 0, 0 },
{0, 0, 0, 0 }
};
Command testCommand;
testCommand.setOperators("-2-", false, true);
std::vector<std::string> trial = testCommand.getCommVector();
std::cout<<"filename:"<<fileName<<std::endl;
std::cout<<"Selected flags:\n"<< "b: "<< byte<<"\nf: "<<field<<"\ncomplement: "<<complement<<std::endl;
return 0;
}
You're iterating way beyond the array size. sizeof(commVector) returns the size of the array in bytes.
If you have C++11 available, you can do this:
for (const auto &s : commVector) {
if (s != "") {
// as before
}
}
Or at least this (if you only have partial C++11 support):
for (auto it = std::begin(commVector); it != std::end(commVector); ++it) {
std::string s = *it;
// the rest as before
}
Without C++11, you can at least do this:
for (int i = 0; i < sizeof(commVector) / sizeof(commVector[0]); ++i) {
// the rest as before
}
Or provide your own function for obtaining the correct array size:
template <class T, size_t N>
size_t arraySize(const T (&)[N]) { return N; }
// Use:
for (size_t i = 0; i < arraySize(commVector); ++i) {
// the rest as before
}
i<sizeof(commVector);
should be
i<countof(commVector);
if countof/_countof is defined for your compiler. If not, you can do it yourself, it is typically defined as:
#define countof(a) (sizeof(a)/sizeof(a[0]))
and I won't go into discussion about using macros in C++ :)
Of course, you could also use a constant are your array has fixed number of elements, but I guess it's just an example.
sizeof returns the size of the object (in this case the string array) itself, not the count of elements inside the vector.
Because of this, it is equal to number of the array elements multiplied by size of a single string instance, so you try to access non-existing items with operator[].
This is also broken:
finalCommVector.push_back("s");
and probably you meant:
finalCommVector.push_back(s);
If all you need is the array of std::string commVector as a std::vector<String>, you can use std::vecor::assign:
finalCommVector.assign(commVector, commVector+3)
The '3' is the length of you array.
I have a struct defined as follows
struct VariableList
{
void Add(simple_instr* instr)
{
//PrintOpcode(instr);
switch(instr->opcode)
{
case STR_OP:
case MCPY_OP:
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
case LDC_OP:
Add(instr->u.ldc.dst);
break;
case BTRUE_OP:
case BFALSE_OP:
Add(instr->u.bj.src);
break;
case CALL_OP:
if (instr->u.call.dst != NO_REGISTER)
{
Add(instr->u.call.dst);
}
Add(instr->u.call.proc);
for (int i = 0; i < instr->u.call.nargs; i++)
{
Add(instr->u.call.args[i]);
}
break;
case MBR_OP:
Add(instr->u.mbr.src);
break;
case RET_OP:
if (instr->u.base.src1 != NO_REGISTER)
Add(instr->u.base.src1);
break;
case CVT_OP:
case CPY_OP:
case NEG_OP:
case NOT_OP:
case LOAD_OP:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
break;
case LABEL_OP:
case JMP_OP:
break;
default:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
}
}
void Add(Variable var)
{
variableList.push_back(var);
}
void RemoveDuplicates()
{
if (variableList.size() > 0)
{
variableList.erase(unique(variableList.begin(), variableList.end()), variableList.end());
currentID = variableList.size();
}
}
VariableList()
{
currentID = 0;
dynamicallyCreated = false;
}
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable* var = new Variable(varList[i]);
if (setLiveness)
{
var->isLive = LiveVal;
}
variableList.push_back(*var);
}
dynamicallyCreated = variableList.size() > 0;
}
Variable& operator[] (int i)
{
return variableList[i];
}
int size()
{
return variableList.size();
}
vector<Variable>::iterator begin()
{
return variableList.begin();
}
vector<Variable>::iterator end()
{
return variableList.end();
}
bool CompareLiveness(VariableList &var)
{
if(variableList.size() != var.size())
{
return false;
}
for (int i = 0; i < variableList.size(); i++)
{
if(variableList[i].isLive != var[i].isLive)
return false;
}
return true;
}
~VariableList()
{
if(dynamicallyCreated)
{
for (vector<Variable>::iterator it = variableList.begin(); it < variableList.end(); ++it)
{
//delete (&it);
}
}
}
protected:
int currentID;
vector<Variable> variableList;
bool dynamicallyCreated;
void Add(simple_reg* reg, bool checkForDuplicates = false)
{
if (reg == null)
{
cout << "null detected" << endl;
return;
}
if (reg->kind == PSEUDO_REG)
{
if (!checkForDuplicates || (checkForDuplicates && find(variableList.begin(), variableList.end(), reg->num) != variableList.end()))
{
cout << "Adding... Reg " << reg->num << endl;
Variable* var = new Variable(reg->num, currentID);
variableList.push_back(*var);
currentID++;
}
}
}
};
I'd like to be able to do a statement like this
VariableList varsIn(Variables, true, false);
that will create a deep copy and allow me to change a few properties. As you can see in my struct, I'm currently attempting to do this using
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable* var = new Variable(varList[i]);
if (setLiveness)
{
var->isLive = LiveVal;
}
variableList.push_back(*var);
}
dynamicallyCreated = variableList.size() > 0;
}
I don't think this is the right way to do it though. What's the proper way to do this sort of copying? Is there a way to do it without using new? For reference, the Variable struct is as follows
struct Variable
{
int id;
int num;
bool isLive;
simple_op opcode;
Variable()
{
id = 0;
num = 0;
opcode = NOP_OP;
vClass = Basic;
isLive = false;
}
Variable(int _num, int _id = 0, simple_op _op = NOP_OP)
{
id = _id;
num = _num;
opcode = _op;
vClass = Basic;
isLive = false;
}
VariableClass GetClass()
{
return vClass;
}
bool operator==(const Variable &var) const
{
return num == var.num;
}
bool operator==(const int &x) const
{
return x == num;
}
protected:
VariableClass vClass;
};
VariableClass and simple_op are enums
Thanks in advance
Your code is not only doing dynamic allocation unnecessarily, it's also leaking Variable instances everywhere. Just use an automatic variable, push_back will make a copy:
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable var(varList[i]);
if (setLiveness)
{
var.isLive = LiveVal;
}
variableList.push_back(var);
}
}
And take out the destructor, you can't delete the elements owned by the vector. If they pointed somewhere, sure, but you're not storing pointers.
Also, here's an even better way:
VariableList(VariableList& other, bool setLiveness = false, bool LiveVal = false)
: currentID(0)
, variableList(other.variableList)
{
if (setLiveness) {
for( int i = 0; i < size(); i++ )
variableList[i].isLive = LiveVal;
}
}