static NormPtr expand_parse_template (NormPtr i) { Template *t = tpls [CODE [i++] - IDENTBASE]; Token **argv = (Token**) alloca (t->argc * sizeof (Token*)), *argvv; int argc, c; NormPtr s; if (CODE [i++] != '(') parse_error (i, "template invokation"); for (argc = 0; argc < t->argc; i++) { s = i; while (CODE [i] != ',' && CODE [i] != ')') i++; argv [argc++] = argvv = (Token*) alloca ((1 + i - s) * sizeof (Token)); intextract (argvv, &CODE [s], i - s); for (c = 0; argvv [c] != -1; c++) if (!tokcmp (argvv [c], TEMPLATE_COMMA)) argvv [c] = ','; else if (!tokcmp (argvv [c], TEMPLATE_PARENTH)) argvv [c] = ')'; if (CODE [i] == ')') break; } if (argc < t->argc) parse_error (i, "too few arguments to template"); if (CODE [i] != ')') parse_error (i, "too many arguments to template"); expand_template (t, argv); return i; }
//////////////////////////////////////////////////////////////////////////////// // static classNum - returns the number of a class name // // Parameters: // aclass : string to scan, prefix should be a class name // pos : returns length of the found class name if result != 0 // // Returns: // The number of a class (CLASS_...) // // pos: see above // int TParameterDeclaration::classNum(const char *aclass, size_t &pos) { int i; if ( !aclass ) return 0; for ( i = 1; i < N_CLASSNAMES; ++i ) { if ( !tokcmp(m_classNames[i], aclass) ) { pos = strlen(m_classNames[i]); return i; } } return 0; }
//////////////////////////////////////////////////////////////////////////////// // static typeNum - returns the number of a type given by name // // Parameters: // aclass : string to scan, prefix should be a type name // pos : returns length of the found type name if result != 0 // // Returns: // The number of a class (TYPE_...) // // pos: see above // int TParameterDeclaration::typeNum(const char *type, size_t &pos) { int i; if ( !type ) return 0; for ( i = 1; i < N_TYPESIZES; ++i ) { if ( !tokcmp(m_typeNames[i], type) ) { pos = strlen(m_typeNames[i]); // let int be integer if ( i == TYPE_INT ) i = TYPE_INTEGER; return i; } } return 0; }
void shell (func_t * scope) { /** * shell - when FACT is run by default it comes to here. The * main user interface for FACT, this function grabs an * expression of input, parses it, runs it, and repeats. It * will continue to do so until the user does a C-d, C-c, * returns a value from the main scope, or calls the exit * function. * * @scope - the scope to use when evaluating expressions. */ FACT_t returned; // The value returned by the interpreter. unsigned int end_line; // ... unsigned int hold_line; // ... int *newlines; char *input; char *hold_input; // Used in the main loop to check for else clauses. char **tokenized; // input, tokenized. char **hold_tokens; // Also used to check for else clauses. /* Before we start, print out the copyright info, logo and * a guide to some helpful functions. */ print_logo (); printf ("The FACT programming language interactive shell\n" "© 2010, 2011 Matthew Plant, under the GPL version 3.\n"); hold_input = NULL; scope->file_name = "stdin"; scope->line = 1; end_line = 0; for (;;) // Heh, that looks like a spider. { /* Set the line number to end_line, in case we missed any while evaluating * the last expression. */ scope->line += end_line; end_line = 0; // Then, get raw input for an entire expression. if (hold_input == NULL) input = get_input (stdin, &end_line, "S>", "C>"); else { input = hold_input; hold_input = NULL; } /* We do two checks for EOF signals: once before tokenizing, and once after. * I am not completely sure as to why this is the case, but I do remember at * some point it didn't exit so I added the second check. */ if (input == NULL) break; // Tokenize the input. tokenized = get_words (input); if (tokenized == NULL) break; /* If the first token in the expression is if/on_error, continue to get input * as long as the first token is else. I could forsee this being an issue in * places where the else is placed erroneosly, but that'll be fixed later I * assume. */ if ((tokenized[0][0] == '\n' && (!tokcmp (tokenized[1], "if") || !tokcmp (tokenized[1], "error"))) || (!tokcmp (tokenized[0], "if") || !tokcmp (tokenized[0], "error"))) { for (;;) { /* Go through all the steps we went through from the start of the loop * down to here. */ hold_input = get_input (stdin, &end_line, "?>", "C>"); if (hold_input == NULL|| (hold_tokens = get_words (hold_input)) == NULL) break; // Check to see if the statement starts with else. if ((hold_tokens[0][0] == '\n' && !tokcmp (hold_tokens[1], "else")) || !tokcmp (hold_tokens[0], "else")) { input[strlen (input) - 1] = '\0'; input = combine_strs (input, hold_input); hold_input = NULL; } else break; } printf ("\n"); tokenized = get_words (input); } // Get the newlines and parse the string. tokenized = parse (tokenized, "stdin", scope->line, &newlines); if (tokenized == NULL) continue; // Reset the instruction pointer. reset_ip (); // Evaluate the expression. returned = eval_expression (scope, make_syn_tree (tokenized, newlines)); /* If there were errors, print them out. Otherwise, * print the value of the variable or the name of * the function returned. */ if (returned.type == ERROR_TYPE) errorman_dump (returned.error); else if (returned.type == VAR_TYPE) printf ("Returned value: %s\n", mpc_get_str (returned.v_point->data)); else printf ("Returned object [%s]\n", returned.f_point->name); /* Check to see if the value is to be returned, and * if so, exit. */ if (returned.return_signal) break; } puts ("\nExiting..."); }