Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    570
  • comments
    2427
  • views
    217354

Untitled

Sign in to follow this  
Mushu

101 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
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!