diff options
| -rw-r--r-- | doc/precedent.1 | 2 | ||||
| -rw-r--r-- | src/eval.c | 27 | ||||
| -rw-r--r-- | src/parse.c | 29 | ||||
| -rw-r--r-- | src/parse.h | 6 |
4 files changed, 42 insertions, 22 deletions
diff --git a/doc/precedent.1 b/doc/precedent.1 index a159148..1365ee8 100644 --- a/doc/precedent.1 +++ b/doc/precedent.1 @@ -74,7 +74,7 @@ literals or key references. The following are examples of key references with ar \-\- Evaluates all its arguments. Subtracts every argument after the first from the first. Returns the result, which is a float if any arguments were floats, or an int if all arguments were ints. \fBprint()\fP -\-\- Evaluates its first argument and prints it to the terminal. +\-\- Evaluates its arguments and writes to the terminal. Writes a newline after all its arguments. .SH AUTHOR Developed and maintained by Kai Stevenson. @@ -256,19 +256,22 @@ sym_t* try_eval_internal(sym_t* symbol, hashtable_t* symbolScope) { } } else if (hash == get_hash("print")) { - sym_t* v = eval(symbol->args[0], symbolScope); - if (v->litType == INT) { - printf("%d\n", symtoi(v)); - } - else if (v->litType == FLOAT) { - printf("%.5f\n", symtof(v)); - } - else if (v->litType == STRING) { - char* s = symtos(v); - printf("%s\n", s); - free(s); + for (int i = 0; i < symbol->argCount; i++) { + sym_t* v = eval(symbol->args[i], symbolScope); + if (v->litType == INT) { + printf("%d", symtoi(v)); + } + else if (v->litType == FLOAT) { + printf("%.5f", symtof(v)); + } + else if (v->litType == STRING) { + char* s = symtos(v); + printf("%s", s); + free(s); + } + destroy_sym(v); } - destroy_sym(v); + printf("\n"); return init_sym_int(1); } else { diff --git a/src/parse.c b/src/parse.c index 3811eae..f8749ac 100644 --- a/src/parse.c +++ b/src/parse.c @@ -77,27 +77,34 @@ void symset_add_symbol(symset_t* symbolSet, sym_t* symbol) { } (symbolSet->symbols)[symbolSet->count - 1] = symbol; } -symset_t* parse_symbols(char** str) { +symset_t* parse_symbols(char** str, int* sLine) { symset_t* symbolSet = malloc(sizeof(symset_t)); symbolSet->count = 0; while (1) { /* clear whitespace */ while (!isalnum(**str) && **str != '"' && **str != '-' && **str != '(' && **str != ')' && **str != '\0') { + /* increment line counter if newline read */ + if (**str == '\n') { + (*sLine)++; + } (*str)++; } + /* ended args, return what we have */ if (**str == ')') { (*str)++; return symbolSet; } + /* EOF. return what we have and expect resolution */ else if (**str == '\0') { return symbolSet; } - char* symbolName = calloc(30, sizeof(char)); + char* symbolName = calloc(50, sizeof(char)); char isFloat = 0; char isString = 0; int i = 0; while (1) { symbolName[i] = **str; + /* do not allow control flow to exit here. strings naturally treat special characters differently */ if (**str == '"') { /* start quote */ if (!isString) { @@ -114,10 +121,13 @@ symset_t* parse_symbols(char** str) { } } else if (!isString) { + /* the non-string symbol contains a decimal. it must be a float */ if (**str == '.') { isFloat = 1; } + /* we've hit a character that cannot be part of the symbol. parse the prior characters as the symbol name */ else if (!isalnum(**str) && **str != '-' && **str != '(') { + /* move the pointer back, because the close paren is needed to return the calling function */ if (**str == ')') { (*str)--; } @@ -152,6 +162,7 @@ symset_t* parse_symbols(char** str) { symset_add_symbol(symbolSet, symbol); break; } + /* special case when symbol is terminated by args */ else if (**str == '(') { (*str)++; symbolName[i] = '\0'; @@ -162,7 +173,7 @@ symset_t* parse_symbols(char** str) { else { symbol = init_sym_key("root"); } - symset_t* symbols = parse_symbols(str); + symset_t* symbols = parse_symbols(str, sLine); for (int s = 0; s < symbols->count; s++) { symbol_add_arg(symbol, symbols->symbols[s]); } @@ -176,6 +187,13 @@ symset_t* parse_symbols(char** str) { } i++; (*str)++; + if (i > 50) { + printf("Parser error on line %d: symbol exceeds maximum length (%d)\n", *sLine, i - 1); + if (isString) { + printf("Did you fail to terminate a string?\n"); + } + return NULL; + } } free(symbolName); } @@ -183,8 +201,11 @@ symset_t* parse_symbols(char** str) { sym_t* parse_symbol_final(char* str) { char** strp = malloc(sizeof(char**)); *strp = str; - symset_t* finalSymset = parse_symbols(strp); + int* linep = malloc(sizeof(int*)); + *linep = 1; + symset_t* finalSymset = parse_symbols(strp, linep); free(strp); + free(linep); sym_t* root = init_sym_key("root"); for (int s = 0; s < finalSymset->count; s++) { symbol_add_arg(root, finalSymset->symbols[s]); diff --git a/src/parse.h b/src/parse.h index 7d3b85b..3d919a8 100644 --- a/src/parse.h +++ b/src/parse.h @@ -2,10 +2,6 @@ #ifndef PARSE #define PARSE -/* keyword hashes */ -#define VAR_H 2317739966u -#define DEFINE_H 1788839250 - typedef enum SymbolProvince { NO_PROVINCE, KEY_REF, @@ -41,7 +37,7 @@ float symtof(sym_t* symbol); char* symtos(sym_t* symbol); void symbol_add_arg(sym_t* symbol, sym_t* arg); void symset_add_symbol(symset_t* symbolSet, sym_t* symbol); -symset_t* parse_symbols(char** str); +symset_t* parse_symbols(char** str, int* sLine); sym_t* parse_symbol_final(char* str); void write_symbol_visual(sym_t* symbol, int offset); |
