Sign in to follow this  
  • entries
    570
  • comments
    2427
  • views
    216029

Untitled

Sign in to follow this  
Mushu

68 views

ARRGH I HATE WRITING PARSERS!

Maybe its lack of experience, maybe I just suck. BUT I HATE THEMSSS PRECIIOUUSSS!! GRAHHH!

So, I've broken the bloody fudgy parser into two parts - one that expands a function in string form, ie:

INPUT: f(x) = 8*x+sinx^2/2
OUTPUT: f(x) = ((8*x)+((sin(x^2))/2))


And one that actually parses it. That doesn't look too bad, does it? And it worked for a while. Until I realized buggers happen when...

INPUT: f(x) = sinx
OUTPUT: f(x) = sinx)


What's happening? The expander searches for the operator token "sin" and finds it at position 0. And it borks.

So I made some changes and some changes and the whole thing is a complete mess right now. It's to the point where I fix the problem and another one arises because of the changes.

It may be time to scrap the expander and start writing it again from scratch.

I HATE WRITING PARSERS :( :(

UPDATE! Okay, I rewrote the whole damn thing. And it appears to be working. Its such an ugly function... UGH. But you know, I wasn't even going to attempt something nice. Once again, I SUCK AT WRITING PARSERS :( :( :(

Just so you can see how shit this code is...

string pawn::equ::expand( string equ, string token ) {
// regexes LOL!
static string bops = "+-*/^=";
static string uops = "log|sin|cos|tan|asin|acos|atan";

string::size_type iBegin = equ.find( token );
string::size_type iEnd = iBegin + token.size();

// loop through the whole equation and find all
// instances of the token.
while ( iBegin != string::npos ) {

// tasks:
// - add a '(' before the expression
// - add a ')' after the expression

// if the thingy was found at the beginning of the
// string, then we need to go ahead and add a "("
// in for it since the search pattern will bork
if ( iBegin == 0 ) {
equ.insert( 0, "(" );
} else {

// need to find an operator that's not in an expression
int pCount = 0;

// work backwards
for ( string::size_type i = iBegin-1; i >= 0 && i < equ.size(); --i ) {
char currChar = equ;

if ( currChar == ')' ) {
pCount++;

} else if ( currChar == '(' ) {
pCount--;

} else if ( bops.find( currChar ) != string::npos ) {
// its a binary operator.
if ( pCount <= 0 ) {
// insert in front of i
equ.insert( i+1, "(" );
break; // exit the loop.
}

} else if ( uops.find( currChar ) != string::npos && i >= 2 ) {
// it might be a unary operator, but not if its closer than 2

// build a lookforward check thing.
string lookahead;

for ( int currPos = 2; currPos >= 0; --currPos )
lookahead += equ[i-currPos];

// see if it exists in the regex
if ( uops.find( currChar ) != string::npos ) {
if ( pCount <= 0 ) {
// insert at end of operator (i)
equ.insert( i+1, "(" );
break;
}
}

// don't have to check for the 4-letter regexes
// since, reading backwards, they're equivalent.
}

// finally, if we're still looking at the end
// add one in.
if ( i == 0 ) {
equ.insert( i, "(" );
break;
}
}
}

// now we've got to place the ")" on the other side of the bugger.

// if its at the end of the expression (which shouldn't be possible)
// we need a special case
if ( iEnd == equ.size() ) {
equ.insert( equ.size(), ")" );
} else {

int pCount = 0;

// work forwards
for ( string::size_type i = iEnd+1; i <= equ.size(); ++i ) {
char currChar = equ; // get the character we're at

// figure out what it means
if ( currChar == '(' ) {
pCount++;

} else if ( currChar == ')' ) {
pCount--;

} else if ( bops.find( currChar ) != string::npos ) {
// binary operator
if ( pCount <= 0 ) {
equ.insert( i, ")" );
break;
}
} else if ( uops.find( currChar ) != string::npos && i <= equ.size()-2 ) {

string lookahead;

for ( int currPos = 0; currPos <= 2; ++currPos )
lookahead = lookahead + equ[currPos+i];

// check if its in the regex
if ( uops.find( lookahead ) != string::npos ) {
if ( pCount <= 0 ) {
equ.insert( i, ")" );
break;
}
}

// figure out the 4-char regex, if there is one.
if ( i <= equ.size()-3 ) {
// only if there is enough room!
lookahead += equ[i+3];
}

// check the regex again
if ( uops.find( lookahead ) != string::npos ) {
if ( pCount <= 0 ) {
equ.insert( i, ")" );
break;
}
}
}

// finally, if we're still looking at the end
// add one in.
if ( i == equ.size() ) {
equ.insert( i, ")" );
break;
}
}
}


// find the next instance of the token -
// starting from the end of this token
// +1 (the parenthesis we added)
iBegin = equ.find( token, iEnd+1 );
iEnd = iBegin + token.size();
}

return equ;
}



BURN YOUR EYES OUT OMG >:( >:( >:(
Sign in to follow this  


2 Comments


Recommended Comments

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now