So I programmed a simple lexer which I currently studying is Language Implementation Patterns.
The codes in the said book is written in JAVA and I've tried to code it using C++.
It just have to recognized the tokens i provided in the program for example and spaces will be skipped:
'[ABCDE , EFGH]'
[ - LBRACK
ABCDE - NAME
, - COMMA
EFGH - NAME
So I build different classes as I convert the classes in JAVA to C++.
Token.h
#pragma once
#include <string>
#include <vector>
using namespace std;
constexpr auto NAME = 2;
constexpr auto COMMA = 3;
constexpr auto LBRACK = 4;
constexpr auto RBRACK = 5;
class Token
{
public:
Token();
~Token();
Token(int , const char * text );
char * to_string();
string tokenNames[6] = { "n/a" , "<EOF>", "NAME", "COMMA", "LBRACK", "RBRACK" };
int token_type() { return this->type; }
private:
int type = 0;
char * text = NULL;
};
Token.cpp
#include "Token.h"
Token::Token() {
}
Token::~Token(){
}
Token::Token(int type, const char * text) {
this->text = (char *)text;
this->type = type;
}
char* Token::to_string() {
char* out_buffer = new char[255];
vector <string> tokenNames;
int size = sizeof(this->tokenNames) / sizeof(this->tokenNames[0]);
for (int i = 0; i <size; i++)
{
tokenNames.push_back(this->tokenNames[i]);
}
printf("%s", this->text);
sprintf(out_buffer, "%s , %s \n", this->text, tokenNames[this->type].c_str());
return out_buffer;
}
Lexer.h
#pragma once
#include <string>
#include <vector>
#include "Token.h"
#define EOF -1
constexpr auto EOF_TYPE = 1;;
using namespace std;
class Lexer
{
public:
Lexer();
~Lexer();
Lexer(vector <char> input);
void consume();
void match(char x);
char get_c() {
return c;
}
vector<char> input;
char c;
private:
int p = 0;
};
Lexer.cpp
#include "Lexer.h"
Lexer::Lexer()
{
}
Lexer::~Lexer()
{
}
Lexer::Lexer(vector <char> input) {
this->input = input;
c = input.at(p);
}
void Lexer::consume() {
p++;
if (p >= this->input.size()) c = EOF;
else c = this->input.at(p);
}
void Lexer::match(char x) {
if (this->c == x) consume();
else throw "wrong input";
}
ListLexer.h
#pragma once
#include <vector>
#include "Token.h"
#include "Lexer.h"
class ListLexer : public Lexer, Token
{
public:
ListLexer();
~ListLexer();
Lexer* lexer;
ListLexer(vector <char> x) {
lexer = new Lexer(x);
c = lexer->get_c();
}
char* get_token_names(int x);
Token* next_token();
void skip_space();
bool is_letter();
char * name();
private:
char c = NULL;
};
ListLexer.cpp
#include "ListLexer.h"
ListLexer::ListLexer()
{
c = lexer->c;
}
ListLexer::~ListLexer()
{
}
char* ListLexer::get_token_names(int x) {
char out_buffer[100];
sprintf(out_buffer, "%s", Token::tokenNames[x]);
return out_buffer;
}
Token* ListLexer::next_token() {
while ((c= lexer->c) != EOF) {
switch (c) {
case ' ': case '\t': case '\n': case '\r': skip_space(); continue;
case '[':
lexer->consume();
return new Token(LBRACK, "LBRACK");
case ']':
lexer->consume();
return new Token(RBRACK, "RBRACK");
case ',':
lexer->consume();
return new Token(COMMA, "COMMA");
default:
if (is_letter()) return new Token(NAME, name());
throw "wrong input";
}
}
return new Token(EOF_TYPE, "EOF");
}
void ListLexer::skip_space() {
while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
consume();
}
bool ListLexer::is_letter() {
return (lexer->c >= 'a' && lexer->c <= 'z') || (lexer->c >= 'A' && lexer->c <= 'Z');
}
char* ListLexer::name() {
vector <char> buffer;
char out_buffer[255];
while (is_letter()) {
buffer.push_back(lexer->c);
lexer->consume();
}
buffer.push_back('\x00');
std::copy(buffer.begin(), buffer.end(), out_buffer);
printf("%s", out_buffer);
return out_buffer;
}
main.cpp
#include <stdio.h>
#include <vector>
#include "Token.h"
#include "Lexer.h"
#include "ListLexer.h"
using namespace std;
int main(int argc, char* argv[])
{
vector <char> vec;
vec.push_back('a');
vec.push_back('b');
vec.push_back('c');
vec.push_back('d');
vec.push_back(',');
vec.push_back('e');
vec.push_back('f');
vec.push_back('g');
vec.push_back('h');
vec.push_back('\xff');
ListLexer* listlexer = new ListLexer(vec);
try {
Token* t = listlexer->next_token();
while (t->token_type() != EOF_TYPE)
{
printf("%s", t->to_string());
t = listlexer->next_token();
}
printf("%s", t->to_string());
}
catch (const char * e) {
printf("Error: %s \n", e);
}
return 0;
}
However, everytime it calls the t->to_string(), the value of text which is should be name "ABCD" or "EFGH" is different.
The highlighted figures are from the ListLexer::name().
The value of the text which is private from the instantiated token class is modified.
Did I miss something? Please help me. Im just learning OOP through this.
Related
I have written a code, but there’s one Problem. When I put cout<<""<<endl; out, I have Bus error: 10. How can I solve this Problem.
This is my code:
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cstdlib>
#include <cstring>
#include <cstdlib>
#include <cstring>
#include <assert.h>
#include <ctime>
#include <sstream>
#include <iostream>
#include <iomanip>
using namespace std;
char* rotate(char const* a, int b)
{
char* r;
for (int i = 0; i < int(strlen(a)); i++) {
if (i >= int(strlen(a)) - b) {
r[i] = a[i - int(int(strlen(a)) - b)];
}
else if (i + b < 0) {
r[i] = a[int(strlen(a) + b)];
}
else {
r[i] = a[i + b];
}
}
r[int(strlen(a))] = '\0';
return r;
}
char* Crypt(char* Input, bool Encrypt, int InitialRotation, int Rotation)
{
char const* Table;
try {
Table = new char[size_t(strlen(Table))];
}
catch (...) {
throw "No Memory";
};
char* a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
try {
a = new char[size_t(strlen(a))];
}
catch (...) {
throw "No Memory";
};
char* ActualTable;
try {
ActualTable = new char[size_t(strlen(ActualTable))];
}
catch (...) {
throw "No Memory";
};
int Offset = InitialRotation;
char* Result;
try {
Result = new char[size_t(strlen(Result))];
}
catch (...) {
throw "No Memory";
};
int b;
Table = "JPGVOUMFYQBENHZRDKASXLICTW";
a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < int(strlen(Input)); i++) {
for (int c = 0; i < int(strlen(a)); c++) {
if (a[c] == Input[i]) {
b = c;
break;
}
}
cout << "" << endl;
ActualTable = rotate(Table, Offset);
Result[i] = rotate(Table, Offset)[b];
Offset = Offset + Rotation;
}
return Result;
}
int main()
{
char* A = "ZZZZ";
cout << Crypt(A, 1, 1, 4) << endl;
return 0;
}
I am trying to find the minimum vertex cover by giving the vertex and edge input in specific format from the user using threads. Here is my code:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cctype>
#include <list>
#include <set>
#include <vector>
#include <climits>
#include <memory>
#include <algorithm>
#include <pthread.h>
#include <unistd.h>
#include "minisat/core/Solver.h"
using namespace std;
static void *AVC2_Vertex_Cover(void *);
void min_vertex_cover_algorithm(Graph &graph_builder){
int ret;
pthread_t AVC2_thread;
ret = pthread_create(&AVC2_thread, NULL, AVC2_Vertex_Cover, &graph_builder);
if(ret)
exit(1);
pthread_join(AVC2_thread, NULL);
pthread_exit(NULL);
}
struct Edge{
unsigned v1,v2;
};
typedef std::vector<unsigned> Vertex_vector;
typedef std::list<unsigned > Vertex_Adjacency_list;
typedef std::vector<Vertex_Adjacency_list> Adjacency_Traversal_list;
struct Graph{
std::size_t no_of_edges;
Adjacency_Traversal_list adjacency_list;
void initialize_graph(unsigned vertices_number);
void construct_edge(Edge edge);
void clear(unsigned vertex);
};
void Graph::initialize_graph(unsigned num){
adjacency_list.clear();
no_of_edges = 0;
adjacency_list.resize(num,{});
}
void Graph::construct_edge(Edge edge) {
auto &literal_1 = adjacency_list[edge.v1];
auto &literal_2 = adjacency_list[edge.v2];
literal_1.push_back(edge.v2);
literal_2.push_back(edge.v1);
no_of_edges ++;
}
void *AVC2_Vertex_Cover(void *input)
{
Graph g = *(const Graph *)input;
unsigned int V = g.adjacency_list.size();
bool visited[V];
for (int i=0; i<V; i++)
visited[i] = false;
for (int u=0; u<V; u++)
{
if (visited[u] == false)
{
for(int x : g.adjacency_list[u])
{
int v = x;
if (visited[v] == false)
{
visited[v] = true;
visited[u] = true;
break;
}
}
}
}
// Print the vertex cover
std::cout << "APPROX-VC-2: ";
for (int i=0; i<V; i++){
if (visited[i])
if(i == V-1)
cout << i << std::endl;
else
cout << i << ",";
}
}
void *IO_thread(void *)
{
Graph &graph_builder = *new Graph();
char character_input;
string my_input;
unsigned int no_of_vertices = 0;
string edge_stream;
char prev_choice = ' ';
while (getline(cin, my_input))
{
istringstream stream_string(my_input);
while (stream_string >> character_input)
{
character_input=(toupper(character_input));
try
{
switch (character_input)
{
case 'V' :
if (prev_choice == 'V')
{
cerr << "Error: V must be followed by E only.\n";
break;
}
else
{
stream_string >> no_of_vertices;
if(no_of_vertices <= 0)
{
throw "Invalid number of vertices";
}
graph_builder.initialize_graph(no_of_vertices);
prev_choice = 'V';
break;
}
case 'E' :
{
unsigned int flag_Entry = 0;
if ( prev_choice == 'E')
{
cerr << "Error: V and E always occur together.\n ";
break;
}
else
{
stream_string >> edge_stream;
istringstream edge_stream_character(edge_stream);
char edg_char;
unsigned int temp = 0;
unsigned int v1;
unsigned int v2;
edge_stream_character >> edg_char;
while (edg_char != '}')
{
edge_stream_character >> edg_char;
if (edg_char == '}')
{
flag_Entry = 1;
break;
}
else
{
edge_stream_character >> temp;
v1 = temp;
edge_stream_character >> edg_char;
edge_stream_character >> temp;
v2 = temp;
edge_stream_character >> edg_char;
edge_stream_character >> edg_char;
if (v1 >= no_of_vertices || v2 >= no_of_vertices)
{
cerr << "Error: Vertex out of range.\n";
graph_builder.adjacency_list.clear();
break;
}
graph_builder.construct_edge({v1,v2});
}
}
if(flag_Entry == 1)
{
prev_choice = 'E';
break;
}
min_vertex_cover_algorithm(graph_builder);
prev_choice = 'E';
break;
}
}
}
}
catch (const char* err)
{
cerr << "Error:" << err << endl;
}
}
}
return 0;
}
int main(int argc, char **argv){
int ret;
pthread_t IO_thread;
ret = pthread_create(&IO_thread, NULL, IO_thread,NULL);
if(ret)
return 1;
pthread_join(IO_thread,NULL);
pthread_exit(NULL);
}
I am getting an error:
unknown type name 'Graph'
void min_vertex_cover_algorithm(Graph &graph_builder){
I am not able to find why this error is occuring. It will be very helpful if I get some solutions.
Just like you, the compiler will read from top to bottom. When it reaches the line:
void min_vertex_cover_algorithm(Graph &graph_builder){
It has to go, ok, lets use a Graph reference. It will look for the declaration of a Graph, which it cannot find, because you have declared (and defined) it below. To solve this, give the compiler a hint. Declare the Graph above the function with:
struct Graph;
void min_vertex_cover_algorithm(Graph &graph_builder){
Or simply move the whole struct definition above the function.
Aim is to make sure that the user entered input for string 1 and string 2 contains only characters A,T,G or C in any order. If either string contains another other character then error should be displayed. Example:
Input contains error
Error in String #1: aacgttcOgMa
Error in String #2: ggataccaSat
This is my attempt at LCS.cpp file code:
#include "LCS.h"
#include <string>
using namespace std;
bool validate(string strX, string strY)
{
string x = strX;
string y = strY;
char searchItem = 'A';
char searchItem = 'C';
char searchItem = 'G';
char searchItem = 'T';
int numOfChar = 0;
int m = strX.length();
int n = strY.length();
for (int i = 0; i < m; i++)
{
if (x[i] == searchItem)
{
numOfChar++;
}
for (int i = 0; i < n; i++)
{
if (y[i] == searchItem)
{
numOfChar++;
}
}
}
This is my LCS.h file code:
#pragma once
#ifndef LCS_H
#define LCS_H
#include <string>
using namespace std;
bool validate(string strX, string strY);
#endif
And my driver file "Driver6.cpp" has this code:
#include "LCS.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strX, strY;
cout << "String #1: ";
cin >> strX;
cout << "String #2: ";
cin >> strY;
//validate the input two strings
if (validate(strX, strY) == false)
{
return 0;
}
int m = strX.length();
int n = strY.length();
}
Didn't really want to do this but it seems like the best bet rather than going round the houses in the comments:
#include <string>
#include <iostream>
bool validate( const std::string & s ) {
for ( auto c : s ) {
if ( c != 'A' && c != 'T' && c != 'C' && c != 'G' ) {
return false;
}
}
return true;
}
int main() {
std::string s1 = "ATGCCCG";
std::string s2 = "ATGfooCCCG";
if ( validate( s1 ) ) {
std::cout << "s1 is valid\n";
}
else {
std::cout << "s1 is not valid\n";
}
if ( validate( s2 ) ) {
std::cout << "s2 is valid\n";
}
else {
std::cout << "s2 is not valid\n";
}
}
Another technique:
bool validate(const std::string& s)
{
const static std::string valid_letters("ATCGatcg");
for (auto c: s)
{
std::string::size_type position = valid_letters.find_first_of(c);
if (position == std::string::npos)
{
return false;
}
}
return true;
}
The above code searches a container of valid letters.
I have created project Calculator in Windows forms. Also I have a logic of my calculator in other cpp file logic.cpp.
The problem: I can't include files logic.cpp and <msclr\marshal_cppstd.h> in Calculator.h.
Also I can include logic.cpp when this file is free from other includes.
Here is code:
Calculator.h
#pragma once
#include "E:\november\CalculatorForm\CalculatorForm\logic.cpp"
#include <msclr\marshal_cppstd.h>
namespace CalculatorForm {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
...
}
logic.cpp
using namespace std;
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool isMultiplicationOrDevision(char c) {
if (c == '*' || c == '/')return true;
return false;
}
bool isSumOrSubtraction(char c) {
if (c == '+' || c == '-')return true;
return false;
}
double doOp(char c, double a, double b) {
switch (c)
{
case '*':
return a*b;
case '/':
if (!b) {
return 0;
}
return a / b;
case '+':
return a + b;
case '-':
return a - b;
default:
return 0;
}
}
class Expression {
private:
vector<double> values;
vector<char> operators;
public:
Expression(string expr) {
string t;
for each (char c in expr)
{
if (c == '+' || c == '-' || c == '/' || c == '*') {
values.push_back(stod(t));
t.clear();
operators.push_back(c);
}
else {
t += c;
}
}
values.push_back(stod(t));
}
Expression(vector<double> values, vector<char> operators) {
this->values = values;
this->operators = operators;
}
double getResult() {
auto i = find_if(operators.begin(), operators.end(), isMultiplicationOrDevision);
while (i != operators.end()) {
doOperation(i);
i = find_if(operators.begin(), operators.end(), isMultiplicationOrDevision);
}
i = find_if(operators.begin(), operators.end(), isSumOrSubtraction);
while (i != operators.end()) {
doOperation(i);
i = find_if(operators.begin(), operators.end(), isSumOrSubtraction);
}
return values[0];
}
private:
void doOperation(vector<char>::iterator i) {
int index = distance(operators.begin(), i);
double t = doOp(operators[index], values[index], values[index + 1]);
operators.erase(i);
values.erase(values.begin() + index);
values[index] = t;
}
};
string checkForBrackets(string s) {
for (auto i = s.begin(); i < s.end(); i++) {
string::iterator start;
if (*i == '(') {
int dist = distance(s.begin(), i);
string t(i, s.end());
t.erase(t.begin());
string temp(s.begin(), i);
s = temp + checkForBrackets(t);
i = s.begin();
advance(i, dist);
}
if (*i == ')') {
i = s.erase(i);
string t(s.begin(), i);
Expression e(t);
double res = e.getResult();
s.erase(s.begin(), i);
s = to_string(res) + s;
return s;
}
}
return s;
}
string doCalculating(string t) {
t = checkForBrackets(t);
Expression a(t);
t = to_string(a.getResult());
return t;
}
include the .h files in your .cpp files and add an include guard to prevent the variables and functions from being redeclared
So ive been writing my code for a bit now and im not the best coder in the world. im still learning and consider myself a beginner. im writing a lexical analysis for a concepts class in c++. Ive tried the solutions ive seen on websites like this such as using extern in the header file and using const in the cpp files, but noting works.when i include my header file in 2 separate .cpp files i get this error for all the ints in the header file:
tokens.obj : error LNK2005: "int eND" (?eND##3HA) already defined in main.obj
header file=
#include <string.h>
#include <map>
using namespace std;
extern int lANGLE=1, rANGLE=2,iD=3, eQ=4, sLASH=5, qSTRING=6, oTHER=7, eND=8, tEXT=9;
map <int, int> counter;
extern int getToken(istream *br, string& lexeme);
token.cpp(declaring what getToken does)
#include "suffix.h"
#include <iostream>
#include <fstream>
#include <map>
#include <cctype>
bool slash = false;
bool text = false;
bool quote = false;
bool id = false;
bool equ = false;
bool other = false;
bool qstring = false;
char prev=NULL;
int getToken(istream *in, string& lexeme)
{
char c;
char prev;
lexeme="";
int intSlash = 0;
int intText = 0;
int intQuote = 0;
int intId = 0;
int intEqual = 0;
int intOther = 0;
int intQstring = 0;
int langlec = 0;
int intLangle = 0;
int ranglec = 0;
int intRangle = 0;
if (in->eof())
return eND;
while (in->get(c))
{
switch (c)
{
case '/' :
if (quote == false && langlec > 0)
{
slash = true;
intSlash++;
return 5;
}
break;
case '=' :
if (quote == false && langlec > 0)
{
equ = true;
intEqual++;
return 4;
}
break;
case '<' :
if ( prev != ' ' && langlec == 0)
{intText++ ;
return 9;}
if (quote == false)
{
langlec ++;
intLangle ++;
id = true;
return 1;
}
break;
case '>' :
if (quote != true)
{
ranglec++;
intRangle++;
return 2;
if (langlec > 0)
{
langlec--;
id = false;
}
}
break;
case '"' :
if (langlec > 0 && quote == true)
{
quote = false;
id = true;
intQstring ++;
intOther--;
return 6;
}
else if (langlec > 0)
{
intOther++;
quote = true;
return 7;
}
break;
case ' ':
if ( prev != ' ' && prev != '<' && prev != '>' && quote == false){
if (langlec == 0){
intText++;
return 9;
}
}
else if ( prev != '/' && prev != '=')
{intId++;
return 3;
}
break;
default:
if (quote == true)
{
id = false;
}
else if (id==true)
{
intId++;
id=false;
return 3;
}
prev=c;
}
}
return 0;
}
main.cpp
#include <iostream>
#include <fstream>
#include <map>
#include <cctype>
#include <string>
#include <algorithm>
#include "suffix.h"
using namespace std;
int
main( int argc, char *argv[] )
{
istream *br;
ifstream infile;
// check args and open the file
if( argc == 1 )
br = &cin;
else if( argc != 2 ) {
cout<<"THERE IS A FATAL ERROR"<<endl;
return 1; // print an error msg
} else {
infile.open(argv[1]);
if( infile.is_open() )
br = &infile;
else {
cout << argv[1] << " can't be opened" << endl;
return 1;
}
}
string tokens="";
int typeOfToken;
while(true){
typeOfToken=getToken(br,tokens);
if (counter.count(typeOfToken))
counter[typeOfToken]+=1;
else
counter[typeOfToken]=1;
if(typeOfToken==8)
break;
}
cout<<"total token count: "<<endl;
if (counter[1]!=0)
cout<<"LANGLE: "<<counter[1]<<endl;
if (counter[2]!=0)
cout<<"RANGLE: "<<counter[2]<<endl;
if (counter[9]!=0)
cout<<"TEXT: "<<counter[9]<<endl;
if (counter[3]!=0)
cout<<"ID: "<<counter[3]<<endl;
if (counter[4]!=0)
cout<<"EQ: "<<counter[4]<<endl;
if (counter[5]!=0)
cout<<"SLASH: "<<counter[5]<<endl;
if (counter[6]!=0)
cout<<"QSTRING: "<<counter[6]<<endl;
if (counter[7]!=0)
cout<<"OTHER: "<<counter[7]<<endl;
return 0;
}
extern int lANGLE=1, ... eND=8
This is supposed to be extern declaration, but due to explicit initialization it's actually a definition. So you end up defining all these variables in several translation units, leading to violation of One Definition Rule.
When you fix this, you'll have the same problem with map <int, int> counter;
What you should do is to answer yourself the question, why do you have to declare all of these in a header file. map <int, int> counter; is used only in main.cpp, so move it there. And the int variables can be replaced with one enum, because it seems you are going to use them as return values for getToken().
So it will be something like
enum Token {
lANGLE=1, rANGLE=2,iD=3,...
};
Token getToken(istream *br, string& lexeme);