diff options
| -rw-r--r-- | check/main.p | 34 | ||||
| -rw-r--r-- | check/nesting.p | 69 | ||||
| -rw-r--r-- | main.c | 7 | ||||
| -rw-r--r-- | makefile | 21 | ||||
| -rw-r--r-- | node.c | 17 | ||||
| -rw-r--r-- | node.h | 6 | ||||
| -rw-r--r-- | pc.l | 8 | ||||
| -rw-r--r-- | pc.y | 67 | ||||
| -rw-r--r-- | scope.c | 146 | ||||
| -rw-r--r-- | scope.h | 27 | ||||
| -rw-r--r-- | sem_check.c | 36 | ||||
| -rw-r--r-- | sem_check.h | 8 | ||||
| -rw-r--r-- | tree.c | 7 | ||||
| -rw-r--r-- | tree.h | 3 | 
14 files changed, 421 insertions, 35 deletions
| diff --git a/check/main.p b/check/main.p new file mode 100644 index 0000000..f05808b --- /dev/null +++ b/check/main.p @@ -0,0 +1,34 @@ +program main ( input, output ); + +        var a, b: integer; +        var x,y,z: real; +	var ai :array [1..10] of integer; +	procedure boo (n: integer); +	var a,c: integer; +	begin +		a := n +	end; +	function bar (a: integer) : real; +	var test:integer; +	begin +		test := 2; +		a := 2 +	end; +	procedure foo; +	begin +		a := 33333; +		x := 1e10; +		z := 1e-10; +		y := 2.5543e-2 +	end; +begin +{ TEST } + +	a := 1; +        x := 3.14; +	b := a + 35; +	(* test *) +	for c := 0 to 10 do begin +		for a:= 10 downto 0 do b := a - c +	end +end. diff --git a/check/nesting.p b/check/nesting.p new file mode 100644 index 0000000..6d24b6b --- /dev/null +++ b/check/nesting.p @@ -0,0 +1,69 @@ + +program main ( input, output ); + +        var a, b: integer; +        var x,y,z: real; +	var ai :array [1..10] of integer; +	procedure boo (n: integer); +	var a,c: integer; +	begin +		a := n +	end; +	function bar (a: integer) : real; +	var test:integer; +	begin +		test := 2; +		a := 2 +	end; +	procedure foo; +                procedure foo2; +                        procedure foo13; +                                procedure foo4; +                                        procedure foo5; +                                                procedure foo6; +                                                        procedure foo7; +                                                                procedure foo46; +                                                                        procedure fooaoesut; +                                                                                procedure foosathst; +                                                                                        procedure foothsth; +                                                                                        begin +                                                                                                a := 33333 +                                                                                        end; +                                                                                begin +                                                                                        a := 33333 +                                                                                end; +                                                                        begin +                                                                                a := 33333 +                                                                        end; +                                                                begin +                                                                        a := 33333 +                                                                end; +                                                        begin +                                                                a := 33333 +                                                        end; +                                                begin +                                                        a := 33333 +                                                end; +                                        begin +                                                a := 33333 +                                        end; +                                begin +                                        a := 33333 +                                end; +                        begin +                                a := 33333 +                        end; +                begin +                        a := 33333 +                end; +	begin +		a := 33333 +	end; +begin +{ TEST } + +	a := 1; +        x := 3.14; +	b := a + 35 +	(* test *) +end. @@ -2,12 +2,16 @@  #include <stdlib.h>  #include <assert.h> +#include "node.h" +#include "scope.h"  #include "y.tab.h"  #include "pc.h"  extern char *yytext;  extern int line_num; +scope *cur_scope; +  char* pretty_type(t)  int t;  { @@ -134,6 +138,9 @@ char* msg;  int main()  { +	cur_scope = mkscope(); +	assert(cur_scope); +  	yyparse();  	return 0; @@ -1,21 +1,24 @@ -CC = gcc +CC = tcc  FLAGS = -g  YACC = yacc  LEX = lex -mypc: y.tab.o lex.yy.o tree.o node.o pc.o -	$(CC) $(FLAGS) -o mypc main.o tree.o node.o y.tab.o lex.yy.o -lfl -ly +mypc: y.tab.o lex.yy.o tree.o scope.o node.o pc.o sem_check.o +	$(CC) $(FLAGS) -o mypc main.o tree.o scope.o sem_check.o node.o y.tab.o lex.yy.o -lfl -ly -pc.o: main.c pc.h +pc.o: main.c headers  	$(CC) $(FLAGS) -c main.c -tree.o: tree.c tree.h +tree.o: tree.c headers  	$(CC) $(FLAGS) -c tree.c -hash.o: hash.c hash.h -	$(CC) $(FLAGS) -c hash.c +sem_check.o: sem_check.c headers +	$(CC) $(FLAGS) -c sem_check.c -node.o: node.c node.h +scope.o: scope.c headers +	$(CC) $(FLAGS) -c scope.c + +node.o: node.c headers  	$(CC) $(FLAGS) -c node.c  y.tab.o: y.tab.c @@ -30,5 +33,7 @@ y.tab.c: pc.y  lex.yy.c: pc.l  	$(LEX) -l pc.l +headers: pc.h tree.h sem_check.h y.tab.h scope.h node.h y.tab.c +  clean:  	rm -f mypc *.o y.tab.* lex.yy.* @@ -19,7 +19,7 @@ char *str;  }  /* helpers */ -node* search(root, str) +node* list_search(root, str)  node *root;  char *str;  { @@ -33,7 +33,7 @@ char *str;  	return NULL;  } -node* insert(root, str) /*TODO change to accept double pointer*/ +node* list_insert(root, str) /*TODO change to accept double pointer*/  node *root;  char * str;  { @@ -41,3 +41,16 @@ char * str;  	p->next = root;  	return p;  } + +void free_list(n) +node *n; +{ +	node *tmp; + +	for(tmp = n; tmp;) { +		n = tmp->next; +		free(tmp); +		tmp = NULL; +		tmp = n; +	} +} @@ -13,7 +13,9 @@ typedef struct node_s {  node* mknode(char *);  /* helpers */ -node* search(node*, char *); -node* insert(node*, char*); +node* list_search(node*, char *); +node* list_insert(node*, char*); + +void free_list(node*);  #endif @@ -1,9 +1,11 @@  %{ - +#include "node.h" +#include "scope.h"  #include "y.tab.h"  #include "pc.h"  int line_num=1; +extern scope *cur_scope;  %} @@ -39,13 +41,13 @@ id	[A-Za-z][A-Za-z0-9_]*  "procedure" {  	debug_print(PROC, NULL); -	/*s = push_scope(s);*/ +	push_scope(&cur_scope);  	return PROC;  }  "function" {  	debug_print(FUNC, NULL); -	/*s = push_scope(s);*/ +	push_scope(&cur_scope);  	return FUNC;  } @@ -3,17 +3,15 @@  #include <stddef.h>  #include "node.h" +#include "scope.h"  #include "tree.h"  #include "y.tab.h"  #include "pc.h" -/*#include "sem_check.h"*/ +#include "sem_check.h" -/* -TODO: -- Add checkid() to counter mkid() -*/  extern int yylex(); +extern scope *cur_scope;  %} @@ -71,6 +69,8 @@ extern int yylex();  %type <tval> simple_expr  %type <tval> id_list +%type <tval> param_list +%type <tval> arguments  %type <tval> expr_list  %type <tval> statement @@ -98,11 +98,20 @@ program  id_list  	:ID  	{ -		$$ = mkid($1); +		/*TODO remove check_ids*/ +		node *tmp; +		check_id(cur_scope, $1); + +		tmp = scope_insert(cur_scope, $1); +		$$ = mkid(tmp);  	}  	|id_list ',' ID  	{ -		$$ = mktree(LIST, $1, mkid($3)); +		node *tmp; + +		check_id(cur_scope, $3); +		tmp = scope_insert(cur_scope, $3); +		$$ = mktree(LIST, $1, mkid(tmp));  	}  ; @@ -148,21 +157,31 @@ sub_prog_declaration  	 sub_prog_declarations  	 compound_statement  	{ +		pop_scope(&cur_scope);  	}  ; +/*push_scope called in pc.l*/  sub_prog_head  	:FUNC ID arguments ':' standard_type ';'  	{ +		check_id(cur_scope->prev, $2); +		scope_insert(cur_scope->prev, $2); + +		cur_scope->ret_var = scope_insert(cur_scope, $2); +		cur_scope->ret_var->var_type = $5;  	}  	|PROC ID arguments ';'  	{ +		check_id(cur_scope->prev, $2); +		scope_insert(cur_scope->prev, $2);  	}  ;  arguments  	:'(' param_list ')'  	{ +		$$ = $2;  	}  	|/*empty*/  ; @@ -170,9 +189,11 @@ arguments  param_list  	:id_list ':' type  	{ +		$$ = $1;  	}  	|param_list ';' id_list ':' type  	{ +		$$ = mktree(LIST, $1, $3);  	}  ; @@ -238,22 +259,31 @@ TD: TO | DT;  var  	:ID  	{ -		$$ = mkid($1); +		$$ = mkid(scope_insert(cur_scope,$1));  	}  	|ID '[' expr ']'  	{ -		$$ = mktree(ARRAY_ACCESS, mkid($1), $3); +		node* tmp; +		tmp = scope_insert(cur_scope, $1); + +		$$ = mktree(ARRAY_ACCESS, mkid(tmp), $3);  	}  ;  proc_statement  	:ID  	{ -		$$ = mkid($1); +		node *tmp; + +		tmp = check_exists(cur_scope, $1); +		$$ = mktree(PCALL, mkid(tmp), NULL);  	}  	|ID '(' expr_list ')'  	{ -		$$ = mktree(PCALL, mkid($1), $3); +		node *tmp; + +		tmp = check_exists(cur_scope, $1); +		$$ = mktree(PCALL, mkid(tmp), $3);  	}  ; @@ -304,15 +334,24 @@ term  factor  	:ID  	{ -		$$ = mkid($1); +		node *tmp; + +		tmp = check_exists(cur_scope, $1); +		$$ = mkid(tmp);  	}  	|ID '[' expr ']'  	{ -		$$ = mktree(ARRAY_ACCESS, mkid($1), $3); +		node *tmp; + +		tmp = check_exists(cur_scope, $1); +		$$ = mktree(ARRAY_ACCESS, mkid(tmp), $3);  	}  	|ID '(' expr_list ')'  	{ -		$$ = mktree(FCALL, mkid($1), $3); +		node *tmp; + +		tmp = check_exists(cur_scope, $1); +		$$ = mktree(FCALL, mkid(tmp), $3);  	}  	|INUM  	{ @@ -0,0 +1,146 @@ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> + +#include "node.h" +#include "scope.h" + +scope* mkscope() +{ +	int i; +	 +	scope *p = malloc(sizeof(scope)); +	assert(p); + +	for (i = 0; i < HASH_SIZE; i++) +		p->table[i] = NULL; + +	p->prev = NULL; +	p->ret_var= NULL; + +	return p; +} + +void free_scope(s) +scope *s; +{ +	int i; + +	if (!s) +		return; + +	for (i = 0; i < HASH_SIZE; i++) { +		free_list(s->table[i]); +	} + +	free(s); +	s = NULL; +} + +/*Copied from Compilers, Aho*/ +#define EOS '\0' +int hashpjw(s) +char* s; +{ +	char *p; +	unsigned h = 0, g; + +	for (p = s; *p != EOS; p++) { +		h = (h<<4) + *p; +		if (g = h & 0xf0000000) { +			h^= g>>24; +			h^= g; +		} +	} + +	return h % HASH_SIZE; +} + +void push_scope(root) +scope **root; +{ +	scope *tmp = mkscope(); +	 +	assert(tmp); + +	tmp->prev = *root; +	*root = tmp; +} + +void pop_scope(root) +scope **root; +{ +	scope *tmp; + +	if (!*root) +		return; + +	tmp = *root; +	*root = (*root)->prev; + +	free_scope(tmp); +} + +node* scope_insert(root, name) +scope *root; +char *name; +{ +	int hash = hashpjw(name); + +	node *tmp = root->table[hash]; +	return root->table[hash] = list_insert(tmp, name); +} + +node* scope_search(root, name) +scope *root; +char *name; +{ +	int hash = hashpjw(name); + +	node *tmp = root->table[hash]; +	return list_search(tmp, name); +} + +node* scope_search_all(root, name) +scope *root; +char *name; +{ +	scope *p; +	node *tmp; + +	for (p = root; p; p = p->prev) +		if (tmp = scope_search(p, name)) +			return tmp; + +	return NULL; +} + +node* scope_safe_search(root, name) +scope *root; +char *name; +{ +	scope *p; +	node *tmp; + +	for (p = root; p; p = p->prev) { +		if (tmp = scope_search(p, name)) +			return tmp; +		if (p->ret_var) +			return NULL; +	} + +	return NULL; +} + +void print_scope(s) +scope *s; +{ +	int i; +	node * tmp; +	for (i = 0; i < HASH_SIZE; i++) { +		for( tmp=s->table[i]; tmp; tmp = tmp->next) { +			fprintf(stderr, "\t%s\n", tmp->name); +		} +	} +} @@ -0,0 +1,27 @@ +#ifndef SCOPE_H +#define SCOPE_H + +#define HASH_SIZE 211 + +typedef struct hash { +	node* table[HASH_SIZE]; +	struct hash *prev; +	node* ret_var; +} scope; + +scope* mkscope(); +void free_scope(scope*); + +/*stack routines*/ +void pop_scope(scope**); +void push_scope(scope**); + +/*helpers*/ +node* scope_insert(scope*, char*); +node* scope_search_all(scope*, char*); +node* scope_search(scope*, char*); +node* scope_safe_search_all(scope*, char*); + +/*hash function*/ +int hashpjw(char*); +#endif diff --git a/sem_check.c b/sem_check.c new file mode 100644 index 0000000..637d044 --- /dev/null +++ b/sem_check.c @@ -0,0 +1,36 @@ +#include <assert.h> +#include <stdio.h> + +#include "node.h" +#include "scope.h" +#include "tree.h" +#include "y.tab.h" +#include "pc.h" +#include "sem_check.h" + +void check_id(s, n) +scope *s; +char *n; +{ +	char buf[100]; + +	if (scope_search(s, n)) { +		snprintf(buf, 100, "\"%s\" already defined in scope...\n", n); +		yyerror(buf); +	} +} + +node* check_exists(s, n) +scope *s; +char *n; +{ +	node *tmp; +	char buf[100]; + +	if(!(tmp = scope_search(s,n))) { +		snprintf(buf, 100, "Cannot find \"%s\"\n", n); +		yyerror(buf); +	} + +	return tmp; +} diff --git a/sem_check.h b/sem_check.h new file mode 100644 index 0000000..eef9e96 --- /dev/null +++ b/sem_check.h @@ -0,0 +1,8 @@ +#ifndef SEMCHECK_H +#define SEMCHECK_H + +void check_id(scope*, char*); + +node* check_exists(scope*, char*); + +#endif @@ -23,12 +23,11 @@ ptree *l, *r;  	return t;  } -ptree* mkid(str) -char *str; +ptree* mkid(n) +node *n;  {  	ptree *p = mktree(ID, NULL, NULL); -	p->attr.nval = malloc(sizeof(node)); /*TODO fix hacky node create*/ -	p->attr.nval->name = strdup(str); /* memory leak? double strdup*/ +	p->attr.nval = n; /* memory leak? double strdup*/  	return p;  } @@ -6,7 +6,6 @@ typedef struct parse_tree {  	union {  		int ival; /* NUM */  		float rval; /* RNUM */ -		char *sval; /* ID */  		node *nval;  		int opval; /* RELOP: LT LE GT GE EQ NE  			      ADDOP: PLUS MINUS OR @@ -20,7 +19,7 @@ void aux_tree_print(ptree*, int);  void print_tree(ptree*);  ptree* mktree(int, ptree*, ptree*); -ptree* mkid(char*); +ptree* mkid(node*);  ptree* mkinum(int);  ptree* mkrnum(float);  ptree* mkop(int, int, ptree*, ptree*); | 
