/* parses(source) -> boolean */ int DuckParses(int argument_count, void* data) { L_TOKEN* lexing; char* buffer; int error = 0; VALUE argument = GetRecord("source", gCurrentContext); gLastExpression.type = VAL_PRIMITIVE; gLastExpression.data.primitive = 0; if (argument.type == VAL_STRING) { lexing = LexSourceBuffer(argument.data.string, &buffer, CONTEXT_FREE_GRAMMAR); if (lexing == NULL) { gLastExpression.data.primitive = -1; FreeLexing(lexing, buffer); //return 1; return 0; } gLastExpression.data.primitive = ParseSucceeds(lexing, PARSE_TABLE, CONTEXT_FREE_GRAMMAR); if (gLastExpression.data.primitive == 0) { FreeLexing(lexing, buffer); return 0; } /* free lexing */ FreeLexing(lexing, buffer); } return error; }
void ClearAllGC() { unsigned int index; /* contexts */ for (index = 0; index < gGCManager.ctx_size; index++) { CONTEXT* context = gGCManager.contexts[index]; ClearContext(context); } /* functions */ for (index = 0; index < gGCManager.func_size; index++) { FUNCTION* function = gGCManager.functions[index]; ClearFunction(function); } /* dictionaries */ for (index = 0; index < gGCManager.table_size; index++) { HASH_TABLE* table = gGCManager.tables[index]; ClearDictionary(table); } /* strings */ for (index = 0; index < gGCManager.str_size; index++) { char* string = gGCManager.strings[index]; ClearString(string); } /* parse tree */ AST_STORE *cur_ast, *next_ast; cur_ast = gGCManager.parseTrees; while (cur_ast) { next_ast = cur_ast->next; FreeParseTree(cur_ast->parseTree); free(cur_ast); cur_ast = next_ast; } /* lexings */ LEXING_STORE *cur_lex, *next_lex; cur_lex = gGCManager.lexings; while (cur_lex) { next_lex = cur_lex->next; FreeLexing(cur_lex->tokens, cur_lex->buffer); free(cur_lex); cur_lex = next_lex; } }
/* eval(source) */ int DuckEval(int argument_count, void* data) { L_TOKEN* lexing; SYNTAX_TREE* ast; char* buffer; int error = 0; VALUE argument = GetRecord("source", gCurrentContext); gLastExpression.type = VAL_NIL; gLastExpression.data.primitive = 0; CLOSURE* currentContext; currentContext = gCurrentContext; int prev_line_error = line_error; SYNTAX_TREE* prev_failed_production = failed_production; // if (gCurrentContext->parent) gCurrentContext = gCurrentContext->parent; gCurrentContext = gGlobalContext; if (argument.type == VAL_STRING) { lexing = LexSourceBuffer(argument.data.string, &buffer, CONTEXT_FREE_GRAMMAR); if (lexing == NULL) { printf("Error lexing source or empty source string.\n"); FreeLexing(lexing, buffer); return 1; } ast = ParseSource(lexing, PARSE_TABLE, CONTEXT_FREE_GRAMMAR); if (ast == NULL) { printf("Error parsing source.\n"); FreeLexing(lexing, buffer); return 1; } /* ReduceProgramAST(&ast); */ error = InterpretNode(ast); if (error) { printf("%s\n", ErrorMessage(error)); PrintStackTrace(); FreeLexing(lexing, buffer); FreeParseTree(ast); ClearCallStack(&gStackTrace); line_error = prev_line_error; failed_production = prev_failed_production; return 1; } /* sanitize last expression for use in program */ //gLastExpression = ReallocStrings(gLastExpression); /* free lexing and parse tree */ //FreeLexing(lexing, buffer); //FreeParseTree(ast); GCAddLexing(lexing, buffer); GCAddParseTree(ast); } gCurrentContext = currentContext; return error; }
/* lex a source buffer for a program */ L_TOKEN* LexSourceBuffer(const char* source_buffer, char** stripped, GRAMMAR_TABLE table) { const char* buffer; char* format; int* lineNumbers; int line; int size; int i, j; int a, b; L_TOKEN* start = NULL; L_TOKEN* end = NULL; buffer = source_buffer; size = strlen(buffer); // count lines lineNumbers = (int*)malloc((size+1)*sizeof(int)); line = 0; for (i = 0; i <= size; i++) { lineNumbers[i] = line; if (buffer[i] == '\n') line++; } // strip clean format = (char*)malloc(size+1); j = 0; for (i = 0; i < size; i++) { if (buffer[i] == '/' && buffer[i+1] == '/') { // inline comments while (i < size && buffer[i] != '\n') i++; i--; } else if (buffer[i] == '/' && buffer[i+1] == '*') { // multiline comments i++; i++; while (i < size - 1 && (buffer[i] != '*' || buffer[i+1] != '/')) { i++; } i++; } #ifdef IGNORE_MACROS else if (buffer[i] == '#') { while (i < size && buffer[i] != '\n') i++; i--; } #endif #ifdef SEMICOLON_COMMENTS else if (buffer[i] == ';') { while (i < size && buffer[i] != '\n') i++; i--; } #endif else if (isSpace(buffer[i])) { // whitespace format[j] = ' '; lineNumbers[j] = lineNumbers[i]; while (i < size && isSpace(buffer[i])) { if (buffer[i] == '\n') { format[j] = '\n'; lineNumbers[j] = lineNumbers[i]; } i++; } i--; j++; } else if (buffer[i] == '"' || buffer[i] == '\'') { char quote = buffer[i]; // string format[j++] = buffer[i++]; while (i < size - 1 && buffer[i] != quote) { if (buffer[i] == '\\') { lineNumbers[j] = lineNumbers[i]; format[j++] = buffer[i++]; } lineNumbers[j] = lineNumbers[i]; format[j++] = buffer[i++]; } lineNumbers[j] = lineNumbers[i]; format[j++] = buffer[i]; } else { // character lineNumbers[j] = lineNumbers[i]; format[j] = buffer[i]; j++; } } format[j] = 0; size = j; // lex // printf("Lexing...\n\n"); for (i = 0; i < size; i++) { line = lineNumbers[i]; if (isAlpha(format[i])) { a = i; // alpha while (i < size && (isAlpha(format[i]) || isNumeric(format[i]) || format[i] == '_')) { i++; } b = i; LexAddBlock(&start, &end, IDENTIFIER(format, a, b, line, table)); i--; } else if (isNumeric(format[i])) { // numeric a = i; while (i < size && isNumeric(format[i])) { i++; } if (format[i] == '.') { i++; while (i < size && isNumeric(format[i])) { i++; } b = i; LexAddBlock(&start, &end, FLOAT(format, a, b, line)); i--; } else { b = i; LexAddBlock(&start, &end, INTEGER(format, a, b, line)); i--; } } else if (format[i] == '"' || format[i] == '\'') { char delimiter = format[i]; // string a = i++; while (i < size && format[i] != delimiter) { i++; } b = i++; LexAddBlock(&start, &end, STRING(format, a, b+1, line)); i--; } else if (isGlyph(format[i])) { a = i; b = 0; // symbol while (i < size && isGlyph(format[i])) { i++; if (FindToken(&format[a], i - a, table)) b = i; } b = b ? b : i; LexAddBlock(&start, &end, TOKEN(format, a, b, line, table)); i = b - 1; } else if (format[i] == '\n') { #ifdef LEX_NEWLINES // end line LexAddBlock(&start, &end, NEWLINE(line)); #endif } else if (format[i] == ' ') { // whitespace } else { // ? PrintLexing(start); printf("Syntax error on line %i: ", line+1); printf("Illegal token %i.\n", format[i]); FreeLexing(start, format); *stripped = 0; return NULL; } } #ifdef LEX_NEWLINES // add newline to the end LexAddBlock(&start, &end, NEWLINE(line)); #endif // add $ to the end LexAddBlock(&start, &end, EOFSYMBOL(line)); free(lineNumbers); *stripped = format; return start; }