/* depend: */
/* cflags: */
-/* linker: atoi.o fdprintf.o */
+/* linker: atoi.o fdprintf.o parser.o */
//#include <malloc.h>
#include <stddef.h>
#include <unistd.h>
#include "atoi.h"
+#include "debug.h"
#include "fdprintf.h"
+#include "parser.h"
/* constants */
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
-/* verbose */
-
-#define ERROR 0
-#define WARNING 1
-#define INFO 2
-#define DEBUG 3
-
-#define VERBOSE(level, statement...) do { if (level <= verbose) { statement; } } while(0)
-
/* gobal variables */
char *progname = NULL;
while ((n = read (stdfdin, pt, BUFFER_SIZE - (pt - buffer))) != 0) {
VERBOSE (DEBUG, PRINTOUT ("read %d bytes\n", n));
n += (pt - buffer);
+ if ((n == 2) && (buffer[0] == '.')) {
+ return 0;
+ }
/* look for end of line */
for (i = 0, j = 0; i < n; i++) {
if (buffer[i] == '\n') {
buffer[i] = 0;
VERBOSE (DEBUG, PRINTOUT ("line(%d): %s\n", j, buffer + j));
+ element_t *element = parser (buffer);
+ if (element == (void *)(-1)) {
+ VERBOSE (WARNING, PRINTOUT ("error while parsing: %s\n", buffer));
+ } else {
+ print_element (element, 0);
+ }
//fsync (stdfdout);
- fflush (stdout);
j = i + 1;
}
}
--- /dev/null
+#include <malloc.h>
+#include <stdlib.h>
+
+#include "debug.h"
+#include "fdprintf.h"
+
+#include "parser.h"
+
+/* compare codes */
+
+int codecmp (char *ref, char *str)
+{
+ int sig;
+
+ while (*ref != '\0') {
+ sig = *str++ - *ref++;
+ if (sig != 0) {
+ return (sig > 0) ? 1 : -1;
+ }
+ }
+
+ return 0;
+}
+
+/* allocate new element */
+
+element_t *newelement (func_t function, int nbops)
+{
+ element_t *new = (element_t *) calloc (1, sizeof (element_t));
+ if (new == NULL) {
+ VERBOSE (ERROR, fdprintf (stdfderr, "can't allocate memory\n"));
+ return NULL;
+ }
+ new->func = function;
+ new->nbops = nbops;
+
+ return new;
+}
+
+/* functions */
+
+#define NB_OPERATORS 7
+
+keyword_t operators[NB_OPERATORS] = {
+ { "+ ", Add, 2, 1 },
+ { "+\t", Add, 2, 1 },
+ { "- ", Sub, 2, 1 },
+ { "- ", Sub, 2, 1 },
+ { "*", Mul, 2, 1 },
+ { "/", Div, 2, 1 },
+ { "^", Pow, 2, 1 }
+};
+
+#define NB_FUNCTIONS 7
+keyword_t functions[NB_FUNCTIONS] = {
+ { "sqrt", Sqr, 1, 4 },
+ { "pow", Pow, 2, 3 },
+ { "cos", Cos, 1, 3 },
+ { "sin", Sin, 1, 3 },
+ { "atan", Atn, 1, 4 },
+ { "exp", Exp, 1, 3 },
+ { "log", Log, 1, 3 }
+};
+
+/* parser function */
+
+element_t *parser (char *str) {
+ element_t *root = NULL;
+ int i;
+
+ /* main loop */
+ while (*str != '\0') {
+ int found = 0;
+ element_t *new = NULL;
+ VERBOSE (DEBUG, PRINTOUT ("Processing: %s\n", str));
+
+ /* skip spaces and tabs */
+
+ if ((*str == ' ') || (*str == '\t')) {
+ str++;
+ continue;
+ }
+
+ /* look for operators */
+
+ for (i = 0; i < NB_OPERATORS; i++) {
+ keyword_t *operator = operators + i;
+ if (codecmp (operator->keyword, str) == 0) {
+ if ((root) && (root->func == Val)) {
+ VERBOSE (DEBUG, PRINTOUT ("Oper: %d\n", operator->func));
+ new = newelement (operator->func, operator->nbops);
+ if (new == NULL) {
+ return (element_t *)-1;
+ }
+ new->ops[0] = root;
+ root = new;
+ } else {
+ return (element_t *)(-1);
+ }
+ str += operator->offset;
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ VERBOSE (DEBUG, PRINTOUT ("stop processing operator\n"));
+ continue;
+ }
+
+ /* look for functions */
+
+ for (i = 0; i < NB_FUNCTIONS; i++) {
+ keyword_t *function = functions + i;
+ if (codecmp (function->keyword, str) == 0) {
+ if (root == NULL) {
+ VERBOSE (DEBUG, PRINTOUT ("Func: %d\n", function->func));
+ new = newelement (function->func, function->nbops);
+ if (new == NULL) {
+ return (element_t *)-1;
+ }
+ root = new;
+ } else {
+ return (element_t *)(-1);
+ }
+ str += function->offset;
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ VERBOSE (DEBUG, PRINTOUT ("stop processing function\n"));
+ continue;
+ }
+
+ /* last attend to detect addition and substraction */
+
+ if (((*str == '-') || (*str == '+')) &&
+ ((*(str + 1) >= '0') && (*(str + 1) <= '9')) &&
+ ((root) && (root->func == Val))) {
+ VERBOSE (DEBUG, PRINTOUT ("Oper: %d\n", Add));
+ new = newelement (Add, 2);
+ if (new == NULL) {
+ return (element_t *)-1;
+ }
+ new->ops[0] = root;
+ root = new;
+ }
+
+ /* look for number */
+
+ if (((*str >= '0') && (*str <= '9')) ||
+ (*str == '.') || (*str == '-') ||(*str == '+')) {
+ char *pt;
+ float value = strtof (str, &pt);
+ VERBOSE (DEBUG, PRINTOUT ("Value: %f\n", value));
+ if (str != pt) {
+ new = newelement (Val, 1);
+ new->value = value;
+ if (new == NULL) {
+ return (element_t *)-1;
+ }
+ if (root == NULL) {
+ root = new;
+ } else {
+ for (i = 0; i < root->nbops; i++) {
+ if (root->ops[i] == NULL) {
+ root->ops[i] = new;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ return (element_t *)-1;
+ }
+ }
+ str = pt;
+ found = 1;
+ }
+ }
+
+ /* error */
+
+ if (!found) {
+ return (element_t *)-1;
+ }
+
+ }
+
+ return root;
+}
+
+/* print element tree */
+
+void print_element (element_t *root, int level)
+{
+ char *func = NULL;
+ int i;
+
+ if (root == NULL)
+ return;
+
+ for (i = 0; i < level; i++) {
+ PRINTOUT (" ");
+ }
+
+ switch (root->func) {
+ case Val: func = "Value"; break;
+ case Add: func = "Addition"; break;
+ case Sub: func = "Subtraction"; break;
+ case Mul: func = "Multiplication"; break;
+ case Div: func = "Division"; break;
+ case Pow: func = "Power"; break;
+ case Sqr: func = "Square Root"; break;
+ case Cos: func = "Cosine"; break;
+ case Sin: func = "Sine"; break;
+ case Atn: func = "Arc Tangent"; break;
+ case Log: func = "Logarithm"; break;
+ case Exp: func = "Exponantial"; break;
+ }
+
+ PRINTOUT ("Function: %s\n", func);
+
+ if (root->func == Val) {
+ for (i = 0; i < level; i++) {
+ PRINTOUT (" ");
+ }
+ PRINTOUT ("value: %f\n", root->value);
+ } else {
+ for (i = 0; i < root->nbops; i++) {
+ print_element (root->ops[i], level + 1);
+ }
+ }
+}
+
+/* vim: set ts=4 sw=4 et: */