Exemplo n.º 1
0
////////////////////////////////////////////////////////////////////
//     Function: PPInstance::set_failed
//       Access: Private
//  Description: Called when something has gone wrong that prevents
//               the plugin instance from running.  Specifically, this
//               means it failed to load the core API.
////////////////////////////////////////////////////////////////////
void PPInstance::
set_failed() {
  if (!_failed) {
    _failed = true;

    nout << "Plugin failed.\n";

    // Look for the "onpluginfail" token.
    string expression = lookup_token("onpluginfail");

    if (!expression.empty()) {
      // Now attempt to evaluate the expression.
      COleVariant varResult;
      CComPtr<IDispatch> pDispatch;

      CString evalExpression( expression.c_str() );
      HRESULT hr = m_parentCtrl.EvalExpression( pDispatch, evalExpression , varResult ); 
      if (FAILED(hr)) {
        nout << "Unable to eval " << expression << "\n";
      } else {
        nout << "Eval " << expression << "\n";
      }
    }
  }
}
Exemplo n.º 2
0
void CDirectiveData::Encode()
{
	int num;
	int totalsize = 0;

	for (int i = 0; i < TotalAmount; i++)
	{
		if (Entries[i].String == true)
		{
			unsigned char* Data = StrData.GetEntry(Entries[i].num);
			int len = StrData.GetLen(Entries[i].num);
			for (int i = 0; i < len; i++)
			{
				num = Data[i];
				g_fileManager->write(&num,UnitSize);
			}
			totalsize += len*UnitSize;
		} else {
			if (evalExpression(ExpData[Entries[i].num],num) == false)
				return;
			totalsize += UnitSize;
			g_fileManager->write(&num,UnitSize);
		}
	}

	SpaceNeeded = totalsize;
}
Exemplo n.º 3
0
bool CDirectiveArea::Validate()
{
	int NewSize;

	RamPos = g_fileManager->getVirtualAddress();

	if (Start == true)
	{
		if (evalExpression(SizeExpression,NewSize,true) == false)
			return false;

		if (FillExpression.isInitialized())
		{
			if (evalExpression(FillExpression,fillValue,true) == false)
				return false;
		}

		Global.areaData.startArea(RamPos,NewSize,FileNum,FileLine,fillValue);

		if (Size != NewSize)
		{
			Size = NewSize;
			return true;
		} else {
			return false;
		}
	} else {
		if (Global.areaData.getEntryCount() != 0)
		{
			fillValue = Global.areaData.getCurrentFillValue();
			Size = Global.areaData.getCurrentMaxAddress()-g_fileManager->getVirtualAddress();

			if (fillValue != -1)
				g_fileManager->seekVirtual(Global.areaData.getCurrentMaxAddress());
		}

		Global.areaData.endArea();
		return false;
	}
}
Exemplo n.º 4
0
/*=macfunc INCLUDE
 *
 *  what:   Read in and emit a template block
 *  handler_proc:
 *  load_proc:
 *
 *  desc:
 *
 *  The entire contents of the named file is inserted at this point.
 *  The contents of the file are processed for macro expansion.  The
 *  arguments are eval-ed, so you may compute the name of the file to
 *  be included.  The included file must not contain any incomplete
 *  function blocks.  Function blocks are template text beginning with
 *  any of the macro functions @samp{CASE}, @samp{DEFINE}, @samp{FOR},
 *  @samp{IF} and @samp{WHILE}; extending through their respective
 *  terminating macro functions.
=*/
tMacro*
mFunc_Include(tTemplate* pT, tMacro* pMac)
{
    tTemplate *   pNewTpl;
    ag_bool       needFree;
    char const *  pzFile = evalExpression(&needFree);
    tMacro*       pM;

    if (*pzFile != NUL) {
        pNewTpl = loadTemplate(pzFile, pT->pzTplFile);

        /*
         *  Strip off trailing white space from included templates
         */
        pM = pNewTpl->aMacros + (pNewTpl->macroCt - 1);
        if (pM->funcCode == FTYP_TEXT) {
            char* pz  = pNewTpl->pzTemplText + pM->ozText;
            char* pzE = pz + strlen(pz);
            while ((pzE > pz) && IS_WHITESPACE_CHAR(pzE[-1]))  --pzE;

            /*
             *  IF there is no text left, remove the macro entirely
             */
            if (pz == pzE)
                 pNewTpl->macroCt--;
            else *pzE = NUL;
        }

        if (OPT_VALUE_TRACE > TRACE_DEBUG_MESSAGE) {
            fprintf(pfTrace, TRACE_FN_INC_TPL, pNewTpl->pzTplFile);
            if (OPT_VALUE_TRACE == TRACE_EVERYTHING)
                fprintf(pfTrace, TRACE_FN_INC_LINE, pCurTemplate->pzTplFile,
                        pMac->lineNo);
        }

        generateBlock(pNewTpl, pNewTpl->aMacros,
                      pNewTpl->aMacros + pNewTpl->macroCt);
        unloadTemplate(pNewTpl);
        pCurTemplate = pT;
    }

    if (needFree)
        AGFREE((void*)pzFile);

    return pMac + 1;
}
Exemplo n.º 5
0
double ff_eval(char *s, double *const_value, const char **const_name,
               double (**func1)(void *, double), const char **func1_name,
               double (**func2)(void *, double, double), char **func2_name,
               void *opaque){
    Parser p;

    p.stack_index=100;
    p.s= s;
    p.const_value= const_value;
    p.const_name = const_name;
    p.func1      = func1;
    p.func1_name = func1_name;
    p.func2      = func2;
    p.func2_name = func2_name;
    p.opaque     = opaque;

    return evalExpression(&p);
}
Exemplo n.º 6
0
bool CDirectiveData::Validate()
{
	RamPos = g_fileManager->getVirtualAddress();

	int num;
	for (int i = 0; i < TotalAmount; i++)
	{
		if (Entries[i].String == false)
		{
			if (evalExpression(ExpData[Entries[i].num],num,true) == false)
				return false;
			g_fileManager->advanceMemory(UnitSize);
		} else {
			g_fileManager->advanceMemory(StrData.GetLen(Entries[i].num)*UnitSize);
		}
	}

	return false;
}
Exemplo n.º 7
0
static void evalPow(Parser *p){
    int neg= 0;
    if(p->s[0]=='+') p->s++;

    if(p->s[0]=='-'){
        neg= 1;
        p->s++;
    }

    if(p->s[0]=='('){
        p->s++;;
        evalExpression(p);

        if(p->s[0]!=')')
            fprintf(stderr, "Parser: missing )\n");
        p->s++;
    }else{
        evalPrimary(p);
    }

    if(neg) push(p, -pop(p));
}
Exemplo n.º 8
0
void CDirectiveData::writeTempData(TempData& tempData)
{
	int num;

	std::wstring result;
	switch (UnitSize)
	{
	case 1:
		result = L".byte ";
		break;
	case 2:
		result = L".halfword ";
		break;
	case 4:
		result = L".word ";
		break;
	}

	for (int i = 0; i < TotalAmount; i++)
	{
		if (Entries[i].String == true)
		{
			unsigned char* Data = StrData.GetEntry(Entries[i].num);
			int len = StrData.GetLen(Entries[i].num);
			for (int i = 0; i < len; i++)
			{
				result += formatString(L"0x%0*X,",UnitSize*2,Data[i]);
			}
		} else {
			if (evalExpression(ExpData[Entries[i].num],num) == false)
				return;
			result += formatString(L"0x%0*X,",UnitSize*2,num);
		}
	}

	result.pop_back();
	tempData.writeLine(RamPos,result);
}
Exemplo n.º 9
0
/*
 *  eval_true - should a string be interpreted as TRUE?
 *
 *  It is always true unless:
 *
 *  1.  it is the empty string
 *  2.  it starts with a digit and the number evaluates to zero
 *  3.  it starts with either "#f" or "#F"
 *  4.  For its length or its first five characters (whichever is less)
 *      it matches the string "false"
 */
static ag_bool
eval_true(void)
{
    ag_bool needFree;
    ag_bool res = AG_TRUE;
    char const * pz = evalExpression(&needFree);

    if (IS_DEC_DIGIT_CHAR(*pz))
        res = (atoi(pz) == 0) ? AG_FALSE : AG_TRUE;

    else switch (*pz) {
    case NUL:
        res = AG_FALSE;
        break;

    case '#':
        if ((pz[1] == 'f') || (pz[1] == 'F'))
            res = AG_FALSE;
        break;

    case 'f':
    case 'F':
    {
        int len = strlen(pz);
        if (len > 5)
            len = 5;
        if (strneqvcmp(EVAL_TRUE_FALSE_STR, pz, len) == 0)
            res = AG_FALSE;
        break;
    }
    }

    if (needFree)
        AGFREE(pz);

    return res;
}
Exemplo n.º 10
0
/*=macfunc ESAC
 *
 *  what:   Terminate the @code{CASE} Template Block
 *  in-context:
 *
 *  desc:
 *    This macro ends the @code{CASE} function template block.
 *    For a complete description, @xref{CASE}.
=*/
tMacro*
mFunc_Case(tTemplate* pT, tMacro* pMac)
{
    typedef tSuccess (t_match_proc)(char const *, char const *);
    /*
     *  There are only 15 procedures because the case insenstive matching
     *  get mapped into the previous four.  The last three are "match always",
     *  "match if a value was found" "match if no value found".
     */
    static t_match_proc * const match_procs[] = {
        &Select_Compare_Full,
        &Select_Compare_End,
        &Select_Compare_Start,
        &Select_Compare,

        &Select_Equivalent_Full,
        &Select_Equivalent_End,
        &Select_Equivalent_Start,
        &Select_Equivalent,

        &Select_Match_Full,
        &Select_Match_End,
        &Select_Match_Start,
        &Select_Match,

        &Select_Match_Always,
        &Select_Match_Existence,
        &Select_Match_NonExistence
    };

    static char const * const match_names[] = {
        "COMPARE_FULL",
        "COMPARE_END",
        "COMPARE_START",
        "CONTAINS",

        "EQUIVALENT_FULL",
        "EQUIVALENT_END",
        "EQUIVALENT_START",
        "EQUIV_CONTAINS",

        "MATCH_FULL",
        "MATCH_END",
        "MATCH_START",
        "MATCH_WITHIN",

        "MATCH_ALWAYS",
        "MATCH_EXISTENCE",
        "MATCH_NONEXISTENCE"
    };

    tMacro*   pEnd = pT->aMacros + pMac->endIndex;
    ag_bool needFree;
    char const * pzSampleText = evalExpression(&needFree);

    /*
     *  Search through the selection clauses until we either
     *  reach the end of the list for this CASE macro, or we match.
     */
    for (;;) {
        tSuccess mRes;
        pMac = pT->aMacros + pMac->sibIndex;
        if (pMac >= pEnd) {
            if (OPT_VALUE_TRACE >= TRACE_BLOCK_MACROS) {
                fprintf(pfTrace, "CASE string `%s' did not match\n",
                        pzSampleText);

                if (OPT_VALUE_TRACE == TRACE_EVERYTHING)
                    fprintf(pfTrace, zFileLine, pCurTemplate->pzTplFile,
                            pMac->lineNo);
            }

            break;
        }

        /*
         *  The current macro becomes the selected selection macro
         */
        pCurMacro = pMac;
        mRes = (*(match_procs[pMac->funcCode & 0x0F])
               )(pzSampleText, pT->pzTemplText + pMac->ozText);

        /*
         *  IF match, THEN generate and stop looking for a match.
         */
        if (SUCCEEDED(mRes)) {
            if (OPT_VALUE_TRACE >= TRACE_BLOCK_MACROS) {
                fprintf(pfTrace, "CASE string `%s' %s matched `%s'\n",
                        pzSampleText,
                        match_names[pMac->funcCode & 0x0F],
                        pT->pzTemplText + pMac->ozText);

                if (OPT_VALUE_TRACE == TRACE_EVERYTHING)
                    fprintf(pfTrace, zFileLine, pCurTemplate->pzTplFile,
                            pMac->lineNo);
            }

            generateBlock(pT, pMac + 1, pT->aMacros + pMac->sibIndex);
            break;
        }
        else if (OPT_VALUE_TRACE == TRACE_EVERYTHING) {
            fprintf(pfTrace, "CASE no match: `%s' %s vs. `%s'\n",
                    pzSampleText,
                    match_names[pMac->funcCode & 0x0F],
                    pT->pzTemplText + pMac->ozText);
        }
    }

    if (needFree)
        AGFREE((void*)pzSampleText);

    return pEnd;
}
Exemplo n.º 11
0
static double evalPrimary(Parser *p){
    double d, d2=NAN;
    char *next= p->s;
    int i;

    /* number */
    d= strtod(p->s, &next);
    if(next != p->s){
        p->s= next;
        return d;
    }

    /* named constants */
    for(i=0; p->const_name && p->const_name[i]; i++){
        if(strmatch(p->s, p->const_name[i])){
            p->s+= strlen(p->const_name[i]);
            return p->const_value[i];
        }
    }

    p->s= strchr(p->s, '(');
    if(p->s==NULL){
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ( in \"%s\"\n", next);
        return NAN;
    }
    p->s++; // "("
    d= evalExpression(p);
    if(p->s[0]== ','){
        p->s++; // ","
        d2= evalExpression(p);
    }
    if(p->s[0] != ')'){
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ) in \"%s\"\n", next);
        return NAN;
    }
    p->s++; // ")"

         if( strmatch(next, "sinh"  ) ) d= sinh(d);
    else if( strmatch(next, "cosh"  ) ) d= cosh(d);
    else if( strmatch(next, "tanh"  ) ) d= tanh(d);
    else if( strmatch(next, "sin"   ) ) d= sin(d);
    else if( strmatch(next, "cos"   ) ) d= cos(d);
    else if( strmatch(next, "tan"   ) ) d= tan(d);
    else if( strmatch(next, "exp"   ) ) d= exp(d);
    else if( strmatch(next, "log"   ) ) d= log(d);
    else if( strmatch(next, "squish") ) d= 1/(1+exp(4*d));
    else if( strmatch(next, "gauss" ) ) d= exp(-d*d/2)/sqrt(2*M_PI);
    else if( strmatch(next, "abs"   ) ) d= fabs(d);
    else if( strmatch(next, "max"   ) ) d= d > d2 ? d : d2;
    else if( strmatch(next, "min"   ) ) d= d < d2 ? d : d2;
    else if( strmatch(next, "gt"    ) ) d= d > d2 ? 1.0 : 0.0;
    else if( strmatch(next, "gte"    ) ) d= d >= d2 ? 1.0 : 0.0;
    else if( strmatch(next, "lt"    ) ) d= d > d2 ? 0.0 : 1.0;
    else if( strmatch(next, "lte"    ) ) d= d >= d2 ? 0.0 : 1.0;
    else if( strmatch(next, "eq"    ) ) d= d == d2 ? 1.0 : 0.0;
    else if( strmatch(next, "("     ) ) d= d;
//    else if( strmatch(next, "l1"    ) ) d= 1 + d2*(d - 1);
//    else if( strmatch(next, "sq01"  ) ) d= (d >= 0.0 && d <=1.0) ? 1.0 : 0.0;
    else{
        for(i=0; p->func1_name && p->func1_name[i]; i++){
            if(strmatch(next, p->func1_name[i])){
                return p->func1[i](p->opaque, d);
            }
        }

        for(i=0; p->func2_name && p->func2_name[i]; i++){
            if(strmatch(next, p->func2_name[i])){
                return p->func2[i](p->opaque, d, d2);
            }
        }

        av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next);
        return NAN;
    }

    return d;
}
Exemplo n.º 12
0
static void evalPrimary(Parser *p){
    double d, d2=NAN;
    char *next= p->s;
    int i;

    /* number */
    d= strtod(p->s, &next);
    if(next != p->s){
        push(p, d);
        p->s= next;
        return;
    }

    /* named constants */
    for(i=0; p->const_name[i]; i++){
        if(strmatch(p->s, p->const_name[i])){
            push(p, p->const_value[i]);
            p->s+= strlen(p->const_name[i]);
            return;
        }
    }

    p->s= strchr(p->s, '(');
    if(p->s==NULL){
        fprintf(stderr, "Parser: missing ( in \"%s\"\n", next);
        return;
    }
    p->s++; // "("
    evalExpression(p);
    d= pop(p);
    if(p->s[0]== ','){
        p->s++; // ","
        evalExpression(p);
        d2= pop(p);
    }
    if(p->s[0] != ')'){
        fprintf(stderr, "Parser: missing ) in \"%s\"\n", next);
        return;
    }
    p->s++; // ")"

         if( strmatch(next, "sinh"  ) ) d= sinh(d);
    else if( strmatch(next, "cosh"  ) ) d= cosh(d);
    else if( strmatch(next, "tanh"  ) ) d= tanh(d);
    else if( strmatch(next, "sin"   ) ) d= sin(d);
    else if( strmatch(next, "cos"   ) ) d= cos(d);
    else if( strmatch(next, "tan"   ) ) d= tan(d);
    else if( strmatch(next, "exp"   ) ) d= exp(d);
    else if( strmatch(next, "log10"   ) ) d= log10(d);
    else if( strmatch(next, "log2"   ) ) d= log10(d)/log10(2);
    else if( strmatch(next, "log"   ) ) d= log(d);
    else if( strmatch(next, "sqrt"   ) ) d= sqrt(d);
    else if( strmatch(next, "squish") ) d= 1/(1+exp(4*d));
    else if( strmatch(next, "gauss" ) ) d= exp(-d*d/2)/sqrt(2*M_PI);
    else if( strmatch(next, "abs"   ) ) d= fabs(d);
    else if( strmatch(next, "max"   ) ) d= d > d2 ? d : d2;
    else if( strmatch(next, "min"   ) ) d= d < d2 ? d : d2;
    else if( strmatch(next, "gte"    ) ) d= d >= d2 ? 1.0 : 0.0;
    else if( strmatch(next, "gt"    ) ) d= d > d2 ? 1.0 : 0.0;
    else if( strmatch(next, "lte"    ) ) d= d >= d2 ? 0.0 : 1.0;
    else if( strmatch(next, "lt"    ) ) d= d > d2 ? 0.0 : 1.0;
    else if( strmatch(next, "eq"    ) ) d= d == d2 ? 1.0 : 0.0;
//    else if( strmatch(next, "l1"    ) ) d= 1 + d2*(d - 1);
//    else if( strmatch(next, "sq01"  ) ) d= (d >= 0.0 && d <=1.0) ? 1.0 : 0.0;
    else{
        int error=1;
        for(i=0; p->func1_name && p->func1_name[i]; i++){
            if(strmatch(next, p->func1_name[i])){
                d= p->func1[i](p->opaque, d);
                error=0;
                break;
            }
        }

        for(i=0; p->func2_name && p->func2_name[i]; i++){
            if(strmatch(next, p->func2_name[i])){
                d= p->func2[i](p->opaque, d, d2);
                error=0;
                break;
            }
        }

        if(error){
            fprintf(stderr, "Parser: unknown function in \"%s\"\n", next);
            return;
        }
    }

    push(p, d);
}
Exemplo n.º 13
0
qreal PdfElementText::paint(QPainter *painter) {
	qreal width = toQReal(_attributes.value("stroke", "2"));
	QString strokeColor = _attributes.value("strokecolor", "black");
	QString fillColor = _attributes.value("fillcolor", "");
	QString valign = _attributes.value("valign", "justify");
	QString halign = _attributes.value("halign", "top");
	QString fontfamily = _attributes.value("font", "Aller light");
	QString weight = _attributes.value("weight", "normal");
	qreal size = _attributes.value("size", "12").toFloat();
	bool italic = _attributes.value("italic", "false").toLower() == "true";
	bool underline = _attributes.value("underline", "false").toLower() == "true";
	bool wordwrap = _attributes.value("wordwrap", "true").toLower() == "true";
	qreal x = toQReal(_attributes.value("x", "0"));
	qreal y = toQReal(_attributes.value("y", "0")) + _offsetY;
	qreal w = toQReal(_attributes.value("width", "0"));
	qreal h = toQReal(_attributes.value("height", "0"));
	qreal s = toQReal(_attributes.value("spacing", "0"));

	if (w > 0 && h > 0) {
		QFont font = QApplication::font();
		font.setFamily(fontfamily);
		if (weight == "light") {
			font.setWeight(QFont::Light);
		} else if (weight == "normal") {
			font.setWeight(QFont::Normal);
		} else if (weight == "demibold") {
			font.setWeight(QFont::DemiBold);
		} else if (weight == "bold") {
			font.setWeight(QFont::Bold);
		} else if (weight == "black") {
			font.setWeight(QFont::Black);
		} else {
			font.setWeight(QFont::Normal);
		}
		font.setItalic(italic);
		font.setUnderline(underline);
		font.setPointSizeF(size);

		QPen pen(Qt::black, width, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin);
		painter->setPen(pen);
		painter->setBrush(Qt::black);
		painter->setFont(font);

		int flags = Qt::TextDontClip;
		if (halign == "left") flags |= Qt::AlignLeft;
		else if (halign == "right") flags |= Qt::AlignRight;
		else if (halign == "justify") flags |= Qt::AlignJustify;
		else if (halign == "center") flags |= Qt::AlignHCenter;

		if (valign == "top") flags |= Qt::AlignTop;
		else if (valign == "bottom") flags |= Qt::AlignBottom;
		else if (valign == "center") flags |= Qt::AlignVCenter;

		if (wordwrap) flags |= Qt::TextWordWrap;

		// Replace repeating variables and static ones after
		QString cdata = _attributes.value("cdata", "");
		QHash<QString, QString>::const_iterator it;
		if (_repeating != 0) {
			for (it = _repeating->constBegin(); it != _repeating->constEnd(); it++) {
				cdata.replace(QString("{%1}").arg(it.key()), it.value(), Qt::CaseInsensitive);
			}
		}
		if (_variables != 0) {
			for (it = _variables->constBegin(); it != _variables->constEnd(); it++) {
				// #14 Variables can occure in expressions and show different content in different situations
				evalExpression(&cdata, it.key(), it.value());

				// Replace variables with it's value
				cdata.replace(QString("{%1}").arg(it.key()), it.value(), Qt::CaseInsensitive);
			}
		}

		// split into different paragraphs
		QStringList paragraphs = cdata.split(QRegExp("(\r|\n)"), QString::SkipEmptyParts);

		// paint the text
		QRectF *bounding = new QRectF;
		QRectF rect = QRectF(QPointF(x, y), QSizeF(w, h));
		for (int i = 0; i < paragraphs.size(); i++) {
			painter->drawText(rect, flags, paragraphs.at(i).trimmed(), bounding);
			rect.adjust(0, bounding->height() + s, 0, 0);
		}
	}
	return bottom();
}
Exemplo n.º 14
0
ParseStatus Parser::parseDecl() {
  Token& name = lex[0];
  Token& op1 = lex[1];
  lex += 2;

  assert(name.isIdentifier());
  assert(resolve(name.text).isNil());
  int slot = allocateVariable(name.text);
  Atom& local = stack[slot];
  local.name_ = name.text;

  // Resolve the type expression if present.
  // TODO(aappleby): Allow complex type expressions.
  if (op1.isOperator(OP_COLON))
  {
    Atom type = resolve(lex[0].text);
    assert(!type.isNil());
    local.type_ = type.name_;
    lex++;
    assert(lex[0].isOperator(OP_EQUALS));
    lex++;
  }

  // Evaluate the right hand side.
  evalExpression();
  skipExpected(TT_DELIMITER, DL_SEMICOLON);
  Atom& value = stack.back();

  // Local type is inferred from the expression.
  if (op1.isOperator(OP_DECLARE)) {
    local.type_ = value.type_;
  } else if (local.type_ != value.type_) {
      // Attempt to convert the item to the given type if necessary.
    if (local.type_ == "int32" && value.type_ == "int64") {
      value.type_ = "int32";
    } else if (local.type_ == "float32" && value.type_ == "float64") {
      value.type_ = "float32";
    } else {
      assert(false);
    }
  }

  if (value.isSymbol()) {
    // Move the expression value to the slot.
    local.setValue(value);
    emit(OC_MOVV, slot, stack.size() - 1);
    emit(OC_POP, 1);
  } else {
    // The result of the right-hand expression is a constant.
    // Store it in the constant table and emit a load instruction to place it
    // in the destination register.
    local.ptype_ = value.ptype_;
    local.value_.blob = value.value_.blob;
    value.setName(name.text);
    assert(local == value);
    int cslot = addConstant(value);
    emit(OC_LOADC, slot, cslot);
  }

  stack.pop();
  return PARSE_OK;
}
Exemplo n.º 15
0
ParseStatus Parser::parseAtom() {
  Token t = lex[0];

  if (t.isLiteral()) {
    evalExpression();
    return PARSE_OK;
  }

  Atom temp;

  bool hasName = false;
  bool hasType = false;
  bool hasValue = false;

  if (t.isIdentifier()) {
    // (a | (b
    // Could be name, type, function call, expression.
    // Don't bother handling function call for now.

    // See if the identifier matches a known type.
    Atom resolved = resolve(t.text);

    if (resolved.isType()) {
      // must be type
      temp.type_ = resolved.name_;
      hasType = true;
    } else {
      // must be name
      temp.name_ = t.text;
      hasName = true;
    }
  }

  // First piece done.

  lex++;
  t = lex[0];

  // If the next token is a delimiter, that's the end of the atom.
  if (t.isDelimiter()) {
    stack.push(temp);
    return PARSE_OK;
  }

  if (t.isOperator(OP_DECLARE)) {
    // (a := c)
    parseExpression();
    temp.setValue(stack.back());
    stack.pop();
    return PARSE_OK;
  }

  if (t.isOperator(OP_EQUALS)) {
    assert(!hasName);
    assert(hasType);
    // (b = c)
    parseExpression();
    temp.setValue(stack.pop());
    return PARSE_OK;
  }

  if (t.isOperator(OP_COLON)) {
    // a : b
    assert(hasName);
    assert(!hasType);
    lex++;
    Token b = lex[0];
    temp.type_ = b.text;
    hasType = true;
    lex++;

    t = lex[0];
    if (!t.isOperator(OP_EQUALS)) {
      assert(false);
    }

    lex++;
    parseExpression();
    temp.setValue(stack.pop());
    return PARSE_OK;
  }

  assert(false);
  return PARSE_ERROR;
}