D
DenisNN
Здравствуйте!!! Подскажите пожалуйста почему возникают ошибки линкера?
// main.cpp
#include "parser.h"
int main()
{
char prog_buff[PROG_SIZE];
load_program(prog_buff,"E:/projects/vars_test.dci");
//getch();
return 0;
}[/CODE]
C++:
#include "parser.h"
int main()
{
char prog_buff[PROG_SIZE];
load_program(prog_buff,"E:/projects/vars_test.dci");
//getch();
return 0;
}[/CODE]
C++:
// parser.h
#pragma once
#include "constants_list.h"
#include "variables_list.h"
const int PROG_SIZE = 10000;
// The DCI command tokens.
enum DCItokensT { UNKNCOM, PRINT, INPUT, IF, THEN, FOR, NEXT, TO,
GOTO, GOSUB, RETURN, EOL, FINISHED, END };
// The DCI token types.
enum typesT { UNDEFTOK, OPERATOR, NUMBER, VARIABLE, COMMAND,
STRING, QUOTE };
/* These are the constants used to call serror() when
a syntax error occurs. Add more if you like.
NOTE: SERROR is a generic error message used when
nothing else seems appropriate. */
enum errorsT { SERROR, PARENS, NOEXP, DIV_ZERO, EQUAL_EXP,
NOT_VAR, LAB_TAB_FULL, DUP_LAB, UNDEF_LAB,
THEN_EXP, TO_EXP, TOO_MNY_FOR, NEXT_WO_FOR,
TOO_MNY_GOSUB, RET_WO_GOSUB, MISS_QUOTE };
// check for double op
enum double_ops { LE, GE, NE };
// keyword lookup table
/*
struct commands {
char command[20]; // string form
DCItokensT tok; // internal representation
} table[] = { // commands must be entered lowercase
"print", PRINT, // in this table.
"input", INPUT,
"if", IF,
"then", THEN,
"goto", GOTO,
"for", FOR,
"next", NEXT,
"to", TO,
"gosub", GOSUB,
"return", RETURN,
"end", END,
"", END // mark end of table
};*/
char *prog;
typesT tok_type;
DCItokensT tok;
char token[20];
class parser
{
void serror(errorsT);
DCItokensT look_up(char*); // convert to internal rep
typesT get_token();
public:
parser();
~parser();
bool isdelim(char);
bool is_sp_tab(char);
};
typesT parser::get_token()
{
register char *temp;
tok_type = UNDEFTOK;
temp = token;
*temp = '\0';
if(*prog=='\0') { // end of file
*token = '\0';
tok = FINISHED;
return(tok_type=OPERATOR);
}
if(*prog=='\r')
{ // crlf
++prog; ++prog;
return(tok_type = OPERATOR);
}
while(is_sp_tab(*prog)) ++prog; // skip over white space
if(strchr("+-%*/^=()", *prog)){
tok_type = OPERATOR;
// advance to next char
*temp++ = *prog++;
}
if(strchr("<>", *prog)) { // check for double op
switch(*prog) {
case '<':
if(*(prog+1)=='>') {
prog++; prog++;
*temp = NE;
}
else if(*(prog+1)=='=') {
prog++; prog++;
*temp = LE;
}
else {
prog++;
*temp = '<';
}
temp++;
*temp = '\0';
break;
case '>':
if(*(prog+1)=='=') {
prog++; prog++;
*temp = GE;
}
else {
prog++;
*temp = '>';
}
temp++;
*temp = '\0';
break;
}
return(tok_type = OPERATOR);
}
if(strchr("+-*^/=;(),", *prog)){ // operator
*temp = *prog;
prog++; // advance to next position
temp++;
*temp = '\0';
return (tok_type=OPERATOR);
}
if(*prog=='"') { // quoted string
prog++;
while(*prog!='"'&& *prog!='\r') *temp++ = *prog++;
if(*prog=='\r') serror(MISS_QUOTE);
prog++; *temp = '\0';
return(tok_type=QUOTE);
}
if(isdigit(*prog)) { // number
while(!isdelim(*prog)) *temp++ = *prog++;
*temp = '\0';
return(tok_type = NUMBER);
}
if(isalpha(*prog)) { // var or command
while(!isdelim(*prog)) *temp++ = *prog++;
tok_type = STRING;
}
*temp = '\0';
// see if a string is a command or a variable
if(tok_type==STRING) {
tok = look_up(token); // convert to internal rep
if(!tok) tok_type = VARIABLE;
else tok_type = COMMAND; // is a command
}
return tok_type;
}
/*
/*
if(isalpha(*prog) && strstr(prog,"const")) {
while(*prog != 't') *prog++;*prog++;
while(is_sp_tab(*prog))*prog++;
*temp++ = *prog++;
tok_type = CONSTANT;
}
else if(isalpha(*prog)) {
while(!isdelim(*prog)) *temp++ = *prog++;
return(tok_type = VARIABLE);
}
else if(isdigit(*prog)) {
while(!isdelim(*prog)) *temp++ = *prog++;
return(tok_type = NUMBER);
}
*temp = '\0';
}*/
// Return true if c is a delimiter.
bool parser::isdelim(char c)
{
if(strchr(";,+-<>/*%^=()", c) || c==9 || c=='\r' || c==0)
return true;
return false;
}
// Return true if c is space or tab.
bool parser::is_sp_tab(char c)
{
if(c==' ' || c=='\t') return true;
else return false;
}
// Load a program.
bool load_program(char *p, char *fname)
{
ifstream in(fname, ios::in | ios::binary);
int i=0;
prog = p;
if(!in) {
cout << "File not found ";
cout << "-- be sure to specify .BAS extension.\n";
return false;
}
i = 0;
do {
*p = in.get();
p++; i++;
} while(!in.eof() && i<PROG_SIZE);
// null terminate the program
if(*(p-2)==0x1a) *(p-2) = '\0'; // discard eof marker
else *(p-1) = '\0';
in.close();
return true;
}
/* Look up a token's internal representation in the
token table.
DCItokensT look_up(char *s)
{
register int i;
char *p;
// convert to lowercase
p = s;
while(*p){
*p = tolower(*p);
p++;
}
// see if token is in table
for(i=0; *table[i].command; i++)
if(!strcmp(table[i].command, s))
return table[i].tok;
return UNKNCOM; // unknown command
}*/
// CONSTANTS
/*
if(isalpha(*prog) && strstr(prog,"const")) {
while(*prog != 't') *prog++;*prog++;
while(is_sp_tab(*prog))*prog++;
*temp++ = *prog++;
tok_type = CONSTANT;
}
*/
C++:
//variables_list.h
#pragma once
#include "header.h"
const int SIZE_OF_NAME_C = 20;
class vars_list
{
class node
{
friend class vars_list;
char name[SIZE_OF_NAME_C];
double value;
node *next;
node *prev;
public:
node(){value = 0;}
node(double vl):value(vl)
{ }
~node(){}
};
public:
node *head;
node *tayl;
vars_list(){}
~vars_list(){}
void create(); // create empty list
void add_var(char*,double); // add variable
bool exist(char*); // if exist
};
///////////////////////////////////////////////////
bool vars_list::exist(char *name)
{
node *pHead = head;
while(pHead != tayl)
if(strstr(name,pHead->name))
return true;
else
pHead = pHead->next;
return false;
}
///////////////////////////////////////////////////
void vars_list::create()
{
head = tayl = new node;
head->next = tayl;
tayl->next = 0;
tayl->prev = 0;
}
///////////////////////////////////////////////////
void vars_list::add_var(char *name,double var)
{
node *pnode = new node(var);
pnode->next = head;
pnode->prev = 0;
head->prev = pnode;
head = pnode;
int i = 0;
while(isalpha(*name))
{
head->name[i] = *name;
i++; *name++;
}
head->name[i] = '\0';
}
C++:
//constants_list.h
#pragma once
#include "header.h"
const int SIZE_OF_NAME_V = 20;
class const_list
{
class node
{
friend class const_list;
char name[SIZE_OF_NAME_V];
double value;
node *next;
node *prev;
public:
node(){value = 0;}
node(double vl):value(vl)
{ }
~node(){}
};
public:
node *head;
node *tayl;
const_list(){}
~const_list(){}
void create(); // create empty list
void add_var(char*,double); // add variable
bool exist(char*); // if exist
};
///////////////////////////////////////////////////
bool const_list::exist(char *name)
{
node *pHead = head;
while(pHead != tayl)
if(strstr(name,pHead->name))
return true;
else
pHead = pHead->next;
return false;
}
///////////////////////////////////////////////////
void const_list::create()
{
head = tayl = new node;
head->next = tayl;
tayl->next = 0;
tayl->prev = 0;
}
///////////////////////////////////////////////////
void const_list::add_var(char *name,double var)
{
node *pnode = new node(var);
pnode->next = head;
pnode->prev = 0;
head->prev = pnode;
head = pnode;
int i = 0;
while(isalpha(*name))
{
head->name[i] = *name;
i++; *name++;
}
head->name[i] = '\0';
}
C++:
// header.h
#pragma once
#include <iostream>
#include <fstream>
#include <conio.h>
using namespace std;