void Expr::Parse(void) { Expr *e = AllocExpr(); e->op = ALL_RESOLVED; PushOperator(e); for(;;) { Expr *n = Next(); if(!n) throw "end of expression unexpected"; if(n->op == CONSTANT) { PushOperand(n); Consume(); } else if(n->op == PAREN && n->c == '(') { Consume(); Parse(); n = Next(); if(n->op != PAREN || n->c != ')') throw "expected: )"; Consume(); } else if(n->op == UNARY_OP) { PushOperator(n); Consume(); continue; } else if(n->op == BINARY_OP && n->c == '-') { // The minus sign is special, because it might be binary or // unary, depending on context. n->op = UNARY_OP; n->c = 'n'; PushOperator(n); Consume(); continue; } else { throw "expected expression"; } n = Next(); if(n && n->op == BINARY_OP) { ReduceAndPush(n); Consume(); } else { break; } } while(TopOperator()->op != ALL_RESOLVED) { Reduce(); } PopOperator(); // discard the ALL_RESOLVED marker }
void Expr::ReduceAndPush(Expr *n) { while(Precedence(n) <= Precedence(TopOperator())) { Reduce(); } PushOperator(n); }
/** * Function ReadParam * Read one aperture macro parameter * a parameter can be: * a number * a reference to an aperture definition parameter value: $1 ot $3 ... * a parameter definition can be complex and have operators between numbers and/or other parameter * like $1+3 or $2x2.. * Note minus sign is not always an operator. It can be the sign of a value. * Parameters are separated by a comma ( of finish by *) * @param aText = pointer to the parameter to read. Will be modified to point to the next field * @return true if a param is read, or false */ bool AM_PARAM::ReadParam( char*& aText ) { bool found = false; int ivalue; double dvalue; bool end = false; while( !end ) { switch( *aText ) { case ',': aText++; // fall through case 0: // EOL case '*': // Terminator in a gerber command end = true; break; case ' ': aText++; break; case '$': // defered value defined later, in ADD command which define defered parameters ++aText; ivalue = ReadInt( aText, false ); if( m_index < 1 ) SetIndex( ivalue ); PushOperator( PUSHPARM, ivalue ); found = true; break; case '/': PushOperator( DIV ); aText++; break; case 'x': case 'X': PushOperator( MUL ); aText++; break; case '-': case '+': // Test if this is an operator between 2 params, or the sign of a value if( m_paramStack.size() > 0 && !m_paramStack.back().IsOperator() ) { // Seems an operator PushOperator( *aText == '+' ? ADD : SUB ); aText++; } else { // seems the sign of a value dvalue = ReadDouble( aText, false ); PushOperator( PUSHVALUE, dvalue ); found = true; } break; case '=': // A local definition found like $4=$3/2 // At this point, one defered parameter is expected to be read. // this parameter value (the index) is stored in m_index. // The list of items is cleared aText++; m_paramStack.clear(); found = false; break; default: dvalue = ReadDouble( aText, false ); PushOperator( PUSHVALUE, dvalue ); found = true; break; } } return found; }