static double eval_fn(MSymbol* sym) { double args[4]; unsigned narg = 0; if (!follows(MT_KET)) { while (narg < 4) { MItem* exp = expression(); if (exp->n >= 0) serror("invalid use of list."); args[narg++] = exp->val; if (follows(MT_KET)) break; if (!follows(MT_COMMA)) serror("',' expected."); next_token(); } } next_token(); if (narg < (unsigned long) sym->data) serror("too few arguments to '%s'.", sym->name); if (narg > (unsigned long) sym->data) serror("too many arguments to '%s'.", sym->name); if (narg == 1) return ((double (*)(double)) sym->built_in)(args[0]); else if (narg == 2) return ((double (*)(double, double)) sym->built_in)(args[0], args[1]); error("Internal error."); }
static double term() { double result = power(); while (follows(MT_STAR) || follows(MT_SLASH)) { if (follows(MT_STAR)) { next_token(); result *= power(); } else { next_token(); result /= power(); } } return result; }
static double factor() { if (follows(MT_BRA)) { next_token(); MItem* it = expression(); if (it->n >= 0) serror("invalid use of list."); if (!follows(MT_KET)) serror("')' expected."); next_token(); return it->val; } else if (follows(MT_NUMBER)) { double val = token->value; next_token(); return val; } else if (follows(MT_IDENT)) { MSymbol* sym = peek_symbol(token->text); if (sym == NULL) serror("unknown identifier '%s'.", token->text); next_token(); if (follows(MT_BRA)) { if (sym->built_in == NULL) serror("unknown function '%s'.", sym->name); next_token(); return eval_fn(sym); } else { if (sym->built_in != NULL) serror("invalid use of function."); if (sym->data->n >= 0) serror("invalid use of list."); return sym->data->val; } } else { serror("syntax error: '%s'", token->text); return 0.0; } }
static void assignment(bool debug) { if (!follows(MT_IDENT)) serror("identifier expected."); MSymbol* sym = get_symbol(token->text); next_token(); if (!follows(MT_EQUAL)) serror("'=' expected."); next_token(); sym->data = item(); // semicolon is optional if (follows(MT_SEMICOL)) next_token(); // print numerical temporary variables if (debug) if (sym->data->n < 0) info("%s = %.18g", sym->name, sym->data->val); }
static double power() { double base = factor(); if (follows(MT_POWER)) { next_token(); return pow(base, factor()); } return base; }
static void list(MItem* parent) { parent->list = NULL; parent->n = 0; if (follows(MT_END)) { next_token(); return; } parent->list = item(); parent->n++; MItem* it = parent->list; while (follows(MT_COMMA)) { next_token(); it->next = item(); parent->n++; it = it->next; }; if (!follows(MT_END)) serror("'}' expected."); next_token(); }
static MItem* item() { if (follows(MT_BEGIN)) { next_token(); MItem* it = new_item(); list(it); return it; } else return expression(); }
static void list(MItem* parent) { parent->list = NULL; parent->n = 0; if (follows(MT_END)) { next_token(); return; } parent->list = item(); parent->n++; MItem* it = parent->list; while (follows(MT_COMMA)) { next_token(); it->next = item(); parent->n++; it = it->next; }; if (follows(MT_SEMICOL)) { bool one_word_processed = false; while(!follows(MT_END)) { next_token(); if(follows(MT_END)) break; if(one_word_processed++) parent->marker->append(" "); it->next = item_string_marker(); if(token->type == MT_NUMBER) { std::ostringstream sin; sin << token->value; parent->marker->append(sin.str()); } else parent->marker->append(token->text); it = it->next; } } if (!follows(MT_END)) serror("'}' expected."); next_token(); }
void mesh_parser_run(bool debug) { next_token(); while (!follows(MT_EOF)) assignment(debug); }
static MItem* expression() { // special case: expression is a list reference if (follows(MT_IDENT)) { MSymbol* list = peek_symbol(token->text); if (list != NULL && list->built_in == NULL && list->data != NULL && list->data->n >= 0) { next_token(); // only "=", "}", ";" or "," must follow if (!follows(MT_EQUAL) && !follows(MT_END) && !follows(MT_COMMA) && !follows(MT_SEMICOL)) serror("invalid use of list."); return list->data; } } // handle unary + and - double unary = 1.0; if (follows(MT_PLUS) || follows(MT_MINUS)) { if (follows(MT_MINUS)) unary = -1.0; next_token(); } double result = unary * term(); while (follows(MT_PLUS) || follows(MT_MINUS)) { if (follows(MT_PLUS)) { next_token(); result += term(); } else { next_token(); result -= term(); } } MItem* it = new_item(); it->n = -1; it->val = result; return it; }