Всем доброго времени суток.
Последние пару дней, без преувеличения, разбирал синтаксический анализатор, в целом логика кода понятна, но имеется ньюанс. Сам код что ниже особо не читайте, он большой и запутанный, сам не мало литров пива выкушал

, смотрите еще ниже. В книге полного описания и разбора кода нет к сожелению.
А непонятно следующее: Когда происходит анализ типа лексемы (Number, переменная или оператор), то в двух случаях, когда значение по адресу на который ссылается
exp_ptr является Number или переменная, происходит вызов функции
isdelim() почемуто

проверяет значение на
+-*/%^=() или c==9 или
c=='\r' или c==0, т.е. когда происходит первый вызов, функция без базара возвратит ноль, что повлечет за собой занесение значение в исходный массив и инкрементирование адреса. Далее, что интересно, проверяется следующий символ

Ну к примеру он есть знак
+, получается что функция возвратит 1 и цикл
while прекратится, при этом этот
+ ни куда не заносится, мало того за место него потом будет знак
\0 когда функция подойдет к концу.
Блин кучу лишней инфы наверное привел, если что извините, просто уже второй день парюсь
Может логика у меня кривая, может что не так делаю, подскажите плиз
Вот часть кода.
| Код |
void parser::get_token(){
register char *temp;
tok_type = 0; temp=token; // *temp='\0';
if(!*exp_ptr) return;
while(isspace(*exp_ptr)) ++exp_ptr;
if(strchr("+-*/%^=()", *exp_ptr)){ tok_type=DELIMITER; //Ia?aoia ia neaao?uee neiaie *temp++=*exp_ptr++; } else if(isalpha(*exp_ptr)){ while(!isdelim(*exp_ptr)) *temp++=*exp_ptr++; tok_type=VARIABLE; } else if(isdigit(*exp_ptr)){ while(!isdelim(*exp_ptr)) *temp++=*exp_ptr++; tok_type=NUMBER; } *temp='\0';
} int parser:: isdelim(char c){
if(strchr(" +-*/%^=()", c) || c==9 || c=='\r' ||c==0) return 1; return 0; //
}
|
Полный код:
| Код |
#include<iostream> #include<cstdlib> #include<cctype> #include<cstring> using namespace std;
enum types {DELIMITER =1, VARIABLE, NUMBER};
class parser { char tok_type; char token[80]; char* exp_ptr;
void eval_exp2(double &result); void eval_exp3(double &result); void eval_exp4(double &result); void eval_exp5(double &result); void eval_exp6(double &result); void atom(double &result); void get_token(); void serror(int error); int isdelim(char c);
public: parser(); double eval_exp(char *exp);
};
parser:: parser() { exp_ptr=NULL; };
double parser:: eval_exp(char *exp) { double result; exp_ptr=exp; get_token(); if(!*token) { serror(2); return 0.0; } eval_exp2(result); if(*token) serror(0); return result; } void parser:: eval_exp2(double &result){ register char op; double temp; eval_exp3(result); while((op=*token)=='+' || op=='-') { get_token(); eval_exp3(temp); switch(op){ case '-': result=result-temp; break; case '+': result=result+temp; break;
} } } void parser:: eval_exp3(double &result){ register char op; double temp;
eval_exp4(result); while((op=*token)=='*' || op=='/' || op =='%') { get_token(); eval_exp4(temp); switch(op){ case '*': result = result*temp; break; case '/': result=result/temp; break; case '%': result=(int)result % (int)temp; break; } } } void parser:: eval_exp4(double &result) { double temp, ex; register int t;
eval_exp5(result); if(*token=='^'){ get_token(); eval_exp4(temp); ex=result; if(temp==0.0) { result=1.0; return;
} for(t=(int)temp-1; t>0; --t) result = result*(double)ex; } } void parser:: eval_exp5(double &result) { register char op; op=0; if((tok_type == DELIMITER) && *token=='+' || *token == '-') { op = *token; get_token(); } eval_exp6(result); if(op=='-') result=-result; } void parser:: eval_exp6(double &result) { if(*token =='(') { get_token(); eval_exp2(result); if(*token!=')') serror(1); get_token(); } else atom(result); } void parser:: atom(double &result) { switch(tok_type){ case NUMBER: result=atof(token); get_token(); return; default: serror(0); } } void parser:: serror(int error){
static char *e[]={ "Sintaxicheskii Oshibka", "Balance scoboc", "Pusto" }; cout << e[error] << endl; }
void parser::get_token(){
register char *temp;
tok_type = 0; temp=token; // *temp='\0';
if(!*exp_ptr) return;
while(isspace(*exp_ptr)) ++exp_ptr;
if(strchr("+-*/%^=()", *exp_ptr)){ tok_type=DELIMITER; //Ia?aoia ia neaao?uee neiaie *temp++=*exp_ptr++; } else if(isalpha(*exp_ptr)){ while(!isdelim(*exp_ptr)) *temp++=*exp_ptr++; tok_type=VARIABLE; } else if(isdigit(*exp_ptr)){ while(!isdelim(*exp_ptr)) *temp++=*exp_ptr++; tok_type=NUMBER; } *temp='\0';
} int parser:: isdelim(char c){
if(strchr(" +-*/%^=()", c) || c==9 || c=='\r' ||c==0) return 1; return 0; //
}
int main() { char expstr[80];
cout<<"Aey ieii?aiey aaaaeoa oi?eo, \n";
parser ob;
for(;;) { cout<<"Aaaaeoa au?a?aiea:"; cin.getline(expstr, 79); if(*expstr=='.') break; cout<<"Ioaao:" << ob.eval_exp(expstr)<<"\n\n"; }; return 0; }
|
Это сообщение отредактировал(а) AlanG - 8.7.2006, 17:12