Browse Source

Added makefile and added trees for storing expressions.

long_to_char
Cameron Weinfurt 3 years ago
parent
commit
8a2d9e38a7
  1. 2
      .gitignore
  2. 13
      Makefile
  3. 56
      expr.c
  4. 41
      expr.h
  5. 37
      main.c
  6. 8
      parse.h
  7. 4
      token.c
  8. 7
      token.h

2
.gitignore

@ -1,3 +1,5 @@
as2-s20.html
in.txt
out.txt_sample
*.o
infcalc

13
Makefile

@ -0,0 +1,13 @@
objs = main.o token.o expr.o
build: $(objs)
gcc -o infcalc $(objs)
main.o: main.c expr.h
gcc -c main.c -o main.o
token.o: token.c token.h
gcc -c token.c -o token.o
expr.o: expr.c expr.h
gcc -c expr.c -o expr.o

56
expr.c

@ -0,0 +1,56 @@
#include "expr.h"
expr_t *bubble_expr(expr_t *t, expr_t *n) {
// Is the opcode at the current node in the tree of a higher priority?
if (t->opcode > n->opcode || t->flags & EXFLAG_PAREN) {
// Yes, shift the tree downwards.
n->left.expr = t;
n->par = t->par;
t->par = n;
n->flags |= EXFLAG_LEXP;
return n;
}
// Or is the current node the initial node?
else if (t->opcode == EXPR_NULL) {
n->left.data = t->right.data;
free(t);
return n;
}
else {
// No, descend rightward. Check if it is a leaf or another node first.
if (t->flags & EXFLAG_REXP) {
// There is an expression to the right.
t->right.expr = bubble_expr(t->right.expr, n);
return t;
}
else {
// There is a leaf to the right.
n->left.data = t->right.data;
n->par = t;
t->right.expr = n;
t->flags |= EXFLAG_REXP;
return t;
}
}
}
void print_expr_tree(expr_t *t, int depth) {
fprintf(stderr, "%d (0x%X)\n", t->opcode, t->flags);
for(register int i = depth; i > 0; --i) fputs(" ", stderr);
fprintf(stderr, "");
if (t->flags & EXFLAG_LEXP) {
print_expr_tree(t->left.expr, depth + 1);
}
else {
fprintf(stderr, "%ld\n", t->left.data);
}
for(register int i = depth; i > 0; --i) fputs(" ", stderr);
fprintf(stderr, "");
if (t->flags & EXFLAG_REXP) {
print_expr_tree(t->right.expr, depth + 1);
}
else {
fprintf(stderr, "%ld\n", t->right.data);
}
}

41
expr.h

@ -0,0 +1,41 @@
#ifndef EXPRH
#define EXPRH
#include <stdio.h>
#include <stdlib.h>
#define EXFLAG_LEXP 0x1 // There is an expression on the left.
#define EXFLAG_REXP 0x2 // There is an expression on the right.
#define EXFLAG_LNEG 0x4 // Negate the value on the left.
#define EXFLAG_RNEG 0x8 // Negate the value on the right.
#define EXFLAG_PAREN 0x10 // Override priority due to parenthesises.
#define EXFLAG_MOD1 0x20 // Modifers alter the operation so that similar
#define EXFLAG_MOD2 0x40 // priority operations are the same opcode.
#define EXPR_NULL 0 // Needed for the initial root node.
#define EXPR_ADD 1
#define EXPR_SUB 1 // EXFLAG_RNEG is set.
#define EXPR_MULT100 2 // MOD = 00
#define EXPR_MULT256 2 // MOD = 01
#define EXPR_MULT 2 // MOD = 10
#define EXPR_DIV 2 // MOD = 11
#define EXPR_IPOW 3
typedef struct expr_t {
int flags;
int opcode;
struct expr_t *par;
union {
long data;
struct expr_t *expr;
} left;
union {
long data;
struct expr_t *expr;
} right;
} expr_t;
expr_t *bubble_expr(expr_t *t, expr_t *n);
void print_expr_tree(expr_t *t, int depth);
#endif

37
main.c

@ -1,9 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include "token.h"
#include "expr.h"
expr_t *init_expr(int o, int f, long n) {
expr_t *e = malloc(sizeof(expr_t));
e->opcode = o;
e->flags = f;
e->left.data = 0;
e->right.data = n;
return e;
}
int main() {
expr_t *root, *ap, *m, *ex;
root = init_expr(EXPR_NULL, 0, 3);
ap = init_expr(EXPR_ADD, EXFLAG_PAREN, 2);
m = init_expr(EXPR_MULT, EXFLAG_MOD2, 4);
ex = init_expr(EXPR_IPOW, 0, 2);
print_expr_tree(root, 0);
fprintf(stderr, "-------------------\n");
root = bubble_expr(root, ap);
print_expr_tree(root, 0);
fprintf(stderr, "-------------------\n");
root = bubble_expr(root, ex);
print_expr_tree(root, 0);
fprintf(stderr, "-------------------\n");
root = bubble_expr(root, m);
print_expr_tree(root, 0);
fprintf(stderr, "-------------------\n");
}
/*int main() {
char *line = NULL;
size_t line_len = 0;
getline(&line,&line_len,stdin);
@ -15,4 +48,4 @@ int main() {
printf("%d\n", token);
free(line);
}
}*/

8
parse.h

@ -0,0 +1,8 @@
#ifndef PARSEH
#define PARSEH
#include "token.h"
int parse(const char *str);
#endif

4
token.c

@ -3,8 +3,8 @@
// The first string is where the tokenizer reads from, while the second is set
// when the underlying data needs to be parsed more specifically, like for
// numbers.
char *input_str = NULL;
char *token_str = NULL;
const char *input_str = NULL;
const char *token_str = NULL;
int tokenize() {
token_str = NULL;

7
token.h

@ -1,3 +1,6 @@
#ifndef TOKH
#define TOKH
#include <stddef.h>
#define TOK_NULL 0
@ -13,9 +16,11 @@
#define TOK_FSLASH 9
#define TOK_CARROT 10
extern char *input_str, *token_str;
extern const char *input_str, *token_str;
int tokenize();
#define ISDIGIT(c) (c >= '0' && c <= '9')
#define ISHEX(c) (c & 0xDF >= 'A' && c & 0xDF <= 'F') || ISDIGIT(c)
#endif
Loading…
Cancel
Save