CExpression* CParser::ProcessText (const char *intext) { // and parses the string in intext and returns it. CExpression* expr; text = intext; chcount = 0; if (text.Length() == 0) { return NULL; } ch = text[0]; /* if (ch != '=') { * expr = new CConstExpr(new CStringValue(text)); * *dependent = deplist; * return expr; * } else */ // NextCh(); NextSym(); expr = Expr(); if (sym != eolsym) { CExpression* oldexpr = expr; expr = new COperator2Expr(VALUE_ADD_OPERATOR, oldexpr, Error(STR_String("Extra characters after expression")));//new CConstExpr(new CErrorValue("Extra characters after expression"))); } if (errmsg) errmsg->Release(); return expr; }
void CParser::Term(int s) { // generates an error if the next symbol isn't the specified symbol s // otherwise, skip the symbol if (s == sym) NextSym(); else { STR_String msg; msg.Format("Warning: " + Symbol2Str(s) + " expected\ncontinuing without it"); // AfxMessageBox(msg,MB_ICONERROR); trace(msg); } }
// Run the parser MHParseNode *MHParseText::Parse() { GetNextChar(); // Initialise m_ch NextSym(); // Initialise the symbol values. return DoParse(); }
MHParseNode *MHParseText::DoParse() { MHParseNode *pRes = NULL; try { switch (m_nType) { case PTStartSection: // Open curly bracket { NextSym(); // Should be followed by a tag. if (m_nType != PTTag) Error("Expected ':' after '{'"); MHPTagged *pTag = new MHPTagged(m_nTag); pRes = pTag; NextSym(); while (m_nType != PTEndSection) { pTag->AddArg(DoParse()); } NextSym(); // Remove the close curly bracket. break; } case PTTag: // Tag on its own. { int nTag = m_nTag; MHPTagged *pTag = new MHPTagged(nTag); pRes = pTag; NextSym(); switch (nTag) { case C_ITEMS: case C_LINK_EFFECT: case C_ACTIVATE: case C_ADD: case C_ADD_ITEM: case C_APPEND: case C_BRING_TO_FRONT: case C_CALL: case C_CALL_ACTION_SLOT: case C_CLEAR: case C_CLONE: case C_CLOSE_CONNECTION: case C_DEACTIVATE: case C_DEL_ITEM: case C_DESELECT: case C_DESELECT_ITEM: case C_DIVIDE: case C_DRAW_ARC: case C_DRAW_LINE: case C_DRAW_OVAL: case C_DRAW_POLYGON: case C_DRAW_POLYLINE: case C_DRAW_RECTANGLE: case C_DRAW_SECTOR: case C_FORK: case C_GET_AVAILABILITY_STATUS: case C_GET_BOX_SIZE: case C_GET_CELL_ITEM: case C_GET_CURSOR_POSITION: case C_GET_ENGINE_SUPPORT: case C_GET_ENTRY_POINT: case C_GET_FILL_COLOUR: case C_GET_FIRST_ITEM: case C_GET_HIGHLIGHT_STATUS: case C_GET_INTERACTION_STATUS: case C_GET_ITEM_STATUS: case C_GET_LABEL: case C_GET_LAST_ANCHOR_FIRED: case C_GET_LINE_COLOUR: case C_GET_LINE_STYLE: case C_GET_LINE_WIDTH: case C_GET_LIST_ITEM: case C_GET_LIST_SIZE: case C_GET_OVERWRITE_MODE: case C_GET_PORTION: case C_GET_POSITION: case C_GET_RUNNING_STATUS: case C_GET_SELECTION_STATUS: case C_GET_SLIDER_VALUE: case C_GET_TEXT_CONTENT: case C_GET_TEXT_DATA: case C_GET_TOKEN_POSITION: case C_GET_VOLUME: case C_LAUNCH: case C_LOCK_SCREEN: case C_MODULO: case C_MOVE: case C_MOVE_TO: case C_MULTIPLY: case C_OPEN_CONNECTION: case C_PRELOAD: case C_PUT_BEFORE: case C_PUT_BEHIND: case C_QUIT: case C_READ_PERSISTENT: case C_RUN: case C_SCALE_BITMAP: case C_SCALE_VIDEO: case C_SCROLL_ITEMS: case C_SELECT: case C_SELECT_ITEM: case C_SEND_EVENT: case C_SEND_TO_BACK: case C_SET_BOX_SIZE: case C_SET_CACHE_PRIORITY: case C_SET_COUNTER_END_POSITION: case C_SET_COUNTER_POSITION: case C_SET_COUNTER_TRIGGER: case C_SET_CURSOR_POSITION: case C_SET_CURSOR_SHAPE: case C_SET_DATA: case C_SET_ENTRY_POINT: case C_SET_FILL_COLOUR: case C_SET_FIRST_ITEM: case C_SET_FONT_REF: case C_SET_HIGHLIGHT_STATUS: case C_SET_INTERACTION_STATUS: case C_SET_LABEL: case C_SET_LINE_COLOUR: case C_SET_LINE_STYLE: case C_SET_LINE_WIDTH: case C_SET_OVERWRITE_MODE: case C_SET_PALETTE_REF: case C_SET_PORTION: case C_SET_POSITION: case C_SET_SLIDER_VALUE: case C_SET_SPEED: case C_SET_TIMER: case C_SET_TRANSPARENCY: case C_SET_VARIABLE: case C_SET_VOLUME: case C_SPAWN: case C_STEP: case C_STOP: case C_STORE_PERSISTENT: case C_SUBTRACT: case C_TEST_VARIABLE: case C_TOGGLE: case C_TOGGLE_ITEM: case C_TRANSITION_TO: case C_UNLOAD: case C_UNLOCK_SCREEN: case C_CONTENT_REFERENCE: case C_TOKEN_GROUP_ITEMS: case C_POSITIONS: case C_MULTIPLEX: { // These are parenthesised in the text form. We have to remove the // parentheses otherwise we will return a sequence which will not be // be compatible with the binary form. if (m_nType != PTStartSeq) Error("Expected '('"); NextSym(); while (m_nType != PTEndSeq) pTag->AddArg(DoParse()); NextSym(); // Remove the close parenthesis. break; } case C_ORIGINAL_CONTENT: case C_NEW_GENERIC_BOOLEAN: case C_NEW_GENERIC_INTEGER: case C_NEW_GENERIC_OCTETSTRING: case C_NEW_GENERIC_OBJECT_REF: case C_NEW_GENERIC_CONTENT_REF: case C_ORIGINAL_VALUE: // These always have an argument which may be a tagged item. { // Is it always the case that there is at least one argument so if we haven't // had any arguments yet we should always process a tag as an argument? pTag->AddArg(DoParse()); break; } default: // This can be followed by an int, etc but a new tag is dealt with by the caller. while (m_nType == PTBool ||m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq) { pTag->AddArg(DoParse()); } } break; } case PTInt: { pRes = new MHPInt(m_nInt); NextSym(); break; } case PTBool: { pRes = new MHPBool(m_fBool); NextSym(); break; } case PTString: { MHOctetString str; str.Copy(MHOctetString((const char *)m_String, m_nStringLength)); pRes = new MHPString(str); NextSym(); break; } case PTEnum: { pRes = new MHPEnum(m_nInt); NextSym(); break; } case PTNull: { pRes = new MHPNull; NextSym(); break; } case PTStartSeq: // Open parenthesis. { MHParseSequence *pSeq = new MHParseSequence; pRes = pSeq; NextSym(); while (m_nType != PTEndSeq) pSeq->Append(DoParse()); NextSym(); // Remove the close parenthesis. break; } default: Error("Unexpected symbol"); } return pRes; } catch (...) { delete(pRes); throw; } }
CExpression *CParser::Ex(int i) { // parses an expression in the input, starting at priority i, and // returns an CExpression, containing the parsed input CExpression *e1 = NULL, *e2 = NULL; int opkind2; if (i < NUM_PRIORITY) { e1 = Ex(i + 1); while ((sym == opsym) && (Priority(opkind) == i)) { opkind2 = opkind; NextSym(); e2 = Ex(i + 1); switch (opkind2) { case OPmodulus: e1 = new COperator2Expr(VALUE_MOD_OPERATOR,e1, e2); break; case OPplus: e1 = new COperator2Expr(VALUE_ADD_OPERATOR,e1, e2); break; case OPminus: e1 = new COperator2Expr(VALUE_SUB_OPERATOR,e1, e2); break; case OPtimes: e1 = new COperator2Expr(VALUE_MUL_OPERATOR,e1, e2); break; case OPdivide: e1 = new COperator2Expr(VALUE_DIV_OPERATOR,e1, e2); break; case OPand: e1 = new COperator2Expr(VALUE_AND_OPERATOR,e1, e2); break; case OPor: e1 = new COperator2Expr(VALUE_OR_OPERATOR,e1, e2); break; case OPequal: e1 = new COperator2Expr(VALUE_EQL_OPERATOR,e1, e2); break; case OPunequal: e1 = new COperator2Expr(VALUE_NEQ_OPERATOR,e1, e2); break; case OPgreater: e1 = new COperator2Expr(VALUE_GRE_OPERATOR,e1, e2); break; case OPless: e1 = new COperator2Expr(VALUE_LES_OPERATOR,e1, e2); break; case OPgreaterequal: e1 = new COperator2Expr(VALUE_GEQ_OPERATOR,e1, e2); break; case OPlessequal: e1 = new COperator2Expr(VALUE_LEQ_OPERATOR,e1, e2); break; default: MT_assert(false); break; // should not happen } } } else if (i == NUM_PRIORITY) { if ((sym == opsym) && ( (opkind == OPminus) || (opkind == OPnot) || (opkind == OPplus) ) ) { NextSym(); switch (opkind) { /* +1 is also a valid number! */ case OPplus: e1 = new COperator1Expr(VALUE_POS_OPERATOR, Ex(NUM_PRIORITY)); break; case OPminus: e1 = new COperator1Expr(VALUE_NEG_OPERATOR, Ex(NUM_PRIORITY)); break; case OPnot: e1 = new COperator1Expr(VALUE_NOT_OPERATOR, Ex(NUM_PRIORITY)); break; default: { // should not happen e1 = Error("operator +, - or ! expected"); } } } else { switch (sym) { case constsym: { switch (constkind) { case booltype: e1 = new CConstExpr(new CBoolValue(boolvalue)); break; case inttype: { cInt temp; temp = strtoll(const_as_string, NULL, 10); /* atoi is for int only */ e1 = new CConstExpr(new CIntValue(temp)); break; } case floattype: { double temp; temp = atof(const_as_string); e1 = new CConstExpr(new CFloatValue(temp)); break; } case stringtype: e1 = new CConstExpr(new CStringValue(const_as_string,"")); break; default : MT_assert(false); break; } NextSym(); break; } case lbracksym: NextSym(); e1 = Ex(1); Term(rbracksym); break; case ifsym: { CExpression *e3; NextSym(); Term(lbracksym); e1 = Ex(1); Term(commasym); e2 = Ex(1); if (sym == commasym) { NextSym(); e3 = Ex(1); } else { e3 = new CConstExpr(new CEmptyValue()); } Term(rbracksym); e1 = new CIfExpr(e1, e2, e3); break; } case idsym: { e1 = new CIdentifierExpr(const_as_string,m_identifierContext); NextSym(); break; } case errorsym: { MT_assert(!e1); STR_String errtext="[no info]"; if (errmsg) { CValue* errmsgval = errmsg->Calculate(); errtext=errmsgval->GetText(); errmsgval->Release(); //e1 = Error(errmsg->Calculate()->GetText());//new CConstExpr(errmsg->Calculate()); if ( !(errmsg->Release()) ) { errmsg=NULL; } else { // does this happen ? MT_assert("does this happen"); } } e1 = Error(errtext); break; } default: NextSym(); //return Error("Expression expected"); MT_assert(!e1); e1 = Error("Expression expected"); } } } return e1; }