summaryrefslogtreecommitdiff
path: root/src/user/app/kbasic/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/app/kbasic/expr.c')
-rw-r--r--src/user/app/kbasic/expr.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/user/app/kbasic/expr.c b/src/user/app/kbasic/expr.c
new file mode 100644
index 0000000..3b8d558
--- /dev/null
+++ b/src/user/app/kbasic/expr.c
@@ -0,0 +1,153 @@
+#include <stdlib.h>
+
+#include "basic.h"
+
+void level2(int*), level3(int*), level4(int*), level5(int*), level6(int*), primitive(int*);
+void unary(char, int*), arith(char, int*, int*);
+
+/* Entry point into parser. */
+void get_exp(int *result)
+{
+ get_token();
+ if(!*token) {
+ serror(2);
+ return;
+ }
+ level2(result);
+ putback(); /* return last token read to input stream */
+}
+
+/* Add or subtract two terms. */
+void level2(int *result)
+{
+ register char op;
+ int hold;
+
+ level3(result);
+ while((op = *token) == '+' || op == '-') {
+ get_token();
+ level3(&hold);
+ arith(op, result, &hold);
+ }
+}
+
+/* Multiply or divide two factors. */
+void level3(int *result)
+{
+ register char op;
+ int hold;
+
+ level4(result);
+ while((op = *token) == '*' || op == '/' || op == '%') {
+ get_token();
+ level4(&hold);
+ arith(op, result, &hold);
+ }
+}
+
+/* Process integer exponent. */
+void level4(int *result)
+{
+ int hold;
+
+ level5(result);
+ if(*token== '^') {
+ get_token();
+ level4(&hold);
+ arith('^', result, &hold);
+ }
+}
+
+/* Is a unary + or -. */
+void level5(int *result)
+{
+ register char op;
+
+ op = 0;
+ if((token_type==DELIMITER) && (*token=='+' || *token=='-')) {
+ op = *token;
+ get_token();
+ }
+ level6(result);
+ if(op)
+ unary(op, result);
+}
+
+/* Process parenthesized expression. */
+void level6(int *result)
+{
+ if((*token == '(') && (token_type == DELIMITER)) {
+ get_token();
+ level2(result);
+ if(*token != ')')
+ serror(1);
+ get_token();
+ }
+ else
+ primitive(result);
+}
+
+/* Find value of number or variable. */
+void primitive(int *result)
+{
+
+ switch(token_type) {
+ case VARIABLE:
+ *result = *find_var(token);
+ get_token();
+ return;
+ case NUMBER:
+ *result = atoi(token);
+ get_token();
+ return;
+ case COMMAND:
+ switch(tok) {
+ case RND:
+ *result = rand();
+ get_token();
+ return;
+ }
+ default:
+ serror(0);
+ }
+}
+
+/* Perform the specified arithmetic. */
+void arith(char o, int *r, int *h)
+{
+ register int t, ex;
+
+ switch(o) {
+ case '-':
+ *r = *r-*h;
+ break;
+ case '+':
+ *r = *r+*h;
+ break;
+ case '*':
+ *r = *r * *h;
+ break;
+ case '/':
+ *r = (*r)/(*h);
+ break;
+ case '%':
+ t = (*r)/(*h);
+ *r = *r-(t*(*h));
+ break;
+ case '^':
+ ex = *r;
+ if(*h==0) {
+ *r = 1;
+ break;
+ }
+ for(t=*h-1; t>0; --t) *r = (*r) * ex;
+ break;
+ }
+}
+
+/* Reverse the sign. */
+void unary(char o, int *r)
+{
+ if(o=='-') *r = -(*r);
+}
+