From 536ec62d45af2b1893a2ccd617eb4b7604adf5c9 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Thu, 22 Apr 2010 15:24:08 +0200 Subject: [PATCH] codea: init --- .gitignore | 7 ++ codea/Makefile | 41 ++++++++ codea/code.bfe | 0 codea/parser.y | 231 ++++++++++++++++++++++++++++++++++++++++++++++ codea/scanner.lex | 67 ++++++++++++++ codea/symtable.c | 141 ++++++++++++++++++++++++++++ codea/symtable.h | 23 +++++ 7 files changed, 510 insertions(+) create mode 100644 codea/Makefile create mode 100644 codea/code.bfe create mode 100644 codea/parser.y create mode 100644 codea/scanner.lex create mode 100755 codea/symtable.c create mode 100755 codea/symtable.h diff --git a/.gitignore b/.gitignore index 518f397..300bf9d 100644 --- a/.gitignore +++ b/.gitignore @@ -28,5 +28,12 @@ ag/parser.c ag/parser.h ag/scanner.c +#codea +codea/codea +codea/parser.c +codea/parser.h +codea/scanner.c +codea/code.c + #weitere eintragen... torero/torero.log diff --git a/codea/Makefile b/codea/Makefile new file mode 100644 index 0000000..840aa1b --- /dev/null +++ b/codea/Makefile @@ -0,0 +1,41 @@ +SHELL := bash +NAME := codea +CFLAGS := -ansi -pedantic -D_GNU_SOURCE +OBJS := scanner.o parser.o symtable.o code.o + +all: $(NAME) + +$(NAME): $(OBJS) + @echo " LINK $@" + @gcc -o $@ $(OBJS) -lfl + +scanner.c: oxout.l + @echo " FLEX $<" + @flex -o$@ $< + +%.o: %.c parser.h symtable.h + @echo " CC $<" + @gcc -c $(CFLAGS) $< #-Wall + +parser.c: oxout.y + @echo " YACC $<" + @yacc -t -v -d $< -o $@ + +parser.h: parser.c + +oxout.y oxout.l: parser.y scanner.lex + @echo " OX $^" + @ox $^ + +%.c: %.bfe + @echo " IBURG $<" + @bfe < $< | iburg > $@ + +.PHONY: clean +clean: + rm -f $(NAME) $(OBJS) scanner.c parser.{h,c,output} oxout.{y,l,h} code.c + +1test: 2test + +2test: + /usr/ftp/pub/ublu/test/$(NAME)/test 2>&1 diff --git a/codea/code.bfe b/codea/code.bfe new file mode 100644 index 0000000..e69de29 diff --git a/codea/parser.y b/codea/parser.y new file mode 100644 index 0000000..dbd4e24 --- /dev/null +++ b/codea/parser.y @@ -0,0 +1,231 @@ +%{ + #include + #include + #include + #include "symtable.h" +%} + +%start Input +%token STRUCT END METHOD VAR IF THEN ELSE WHILE DO RETURN NOT OR THIS IDENT NUM ASSIGN + +@macro xxputsin(xx,) + @i xx = @Statement.sin@; +@end + +@macro statinout() + @i @Statement.sout@ = @Statement.sin@; + /* das + *> xxputsin(@Statement.sout@,) + * geht nicht, weil verschachtelte macros deaktiviert sind */ +@end + +@autoinh s +@attributes { char *name; } IDENT +@attributes { struct symbol *f; } FeldID Parms Structdef Program +@attributes { struct symbol *s; } Methoddef Statseq Lexpr Expr Minusterm Multerm Orterm Term Exprs Feld +@attributes { struct symbol *sin; struct symbol *sout; } Statement + +@traversal @postorder c + +%% +Input: + Program + @{ + @i @Program.f@ = tab_new(); + @} + ; + +Program: + Methoddef ';' Program + @{ + @i @Methoddef.s@ = @Program.0.f@; + @i @Program.1.f@ = @Program.0.f@; + @} + + | Structdef ';' Program + @{ + @i @Program.1.f@ = tab_merge(@Program.0.f@, @Structdef.f@, 1); + @} + | + ; + +Methoddef: + METHOD IDENT '(' Parms ')' Statseq END + @{ + @i @Statseq.s@ = tab_merge(@Methoddef.s@, @Parms.f@, 0); + @} + ; + +Structdef: + STRUCT FeldID END + @{ + @i @Structdef.f@ = @FeldID.f@; + @} + ; + +Parms: + /* lokale Vars werden in Statement in die tabelle eingefuegt */ + IDENT Parms + @{ + @i @Parms.0.f@ = tab_add_symbol(@Parms.1.f@, @IDENT.name@, S_VAR, 1); + @} + + | + @{ + @i @Parms.f@ = tab_new(); + @} + ; + +FeldID: + IDENT FeldID + @{ + @i @FeldID.0.f@ = tab_add_symbol(@FeldID.1.f@, @IDENT.name@, S_FIELD, 1); + @} + + | + @{ + @i @FeldID.f@ = tab_new(); + @} + ; + +Statseq: + Statement ';' Statseq + @{ + @i @Statement.sin@ = @Statseq.0.s@; + @i @Statseq.1.s@ = @Statement.sout@; + @} + + | + ; + +Statement: + Lexpr ASSIGN Expr + @{ + statinout() + xxputsin(@Lexpr.s@,) + xxputsin(@Expr.s@,) + @} + + | VAR IDENT ASSIGN Expr + @{ + /* tab_clone ist hier noetig, vgl. folgendes statement + * > var x := x - 1; */ + @i @Statement.sout@ = tab_add_symbol(tab_clone(@Statement.sin@), @IDENT.name@, S_VAR, 1); + xxputsin(@Expr.s@,) + @} + + | Expr + @{ + statinout() + xxputsin(@Expr.s@,) + @} + + | IF Expr THEN Statseq END + @{ + statinout() + xxputsin(@Expr.s@,) + xxputsin(@Statseq.s@,) + @} + + | IF Expr THEN Statseq ELSE Statseq END + @{ + statinout() + xxputsin(@Expr.s@,) + xxputsin(@Statseq.0.s@,) + xxputsin(@Statseq.1.s@,) + @} + + | WHILE Expr DO Statseq END + @{ + statinout() + xxputsin(@Expr.s@,) + xxputsin(@Statseq.s@,) + @} + + | RETURN Expr + @{ + statinout() + xxputsin(@Expr.s@,) + @} + ; + +Lexpr: + IDENT + @{ + @c check(@Lexpr.s@, @IDENT.name@, S_VAR); + @} + + | Feld + ; + +Feld: Term '.' IDENT + @{ + @c check(@Feld.s@, @IDENT.name@, S_FIELD); + @} + ; + +Expr: + Term + | NOT Term + | Term Minusterm + | Term Multerm + | Term Orterm + | Term '<' Term + | Term '=' Term + ; + +Minusterm: + '-' Term Minusterm + | '-' Term + ; + +Multerm: + '*' Term Multerm + | '*' Term + ; + +Orterm: + OR Term Orterm + | OR Term + ; + +Term: + '(' Expr ')' + | NUM + | '-' NUM + | THIS + | IDENT + @{ + @c check(@Term.s@, @IDENT.name@, S_VAR); + @} + + | Feld + | IDENT '(' Exprs ')' + | Term '.' IDENT '(' Exprs ')' + ; + +Exprs: + Expr ',' Exprs + | Expr + | + ; +%% + +extern int yylex(); +extern int yylineno; + +int yyerror(char *error_text) +{ + fprintf(stderr,"Zeile %i: %s\n", yylineno, error_text); + exit(2); +} + +int main(int argc, char **argv) +{ + #if 0 + yydebug=1; + #endif + yyparse(); + return 0; +} + diff --git a/codea/scanner.lex b/codea/scanner.lex new file mode 100644 index 0000000..c104d0f --- /dev/null +++ b/codea/scanner.lex @@ -0,0 +1,67 @@ + #include + #include + #include + #include "parser.h" + +KEYWORD struct|end|method|var|if|then|else|while|do|return|not|or|this +IDENTIFIER [a-zA-Z_][0-9a-zA-Z_]* +NUMBER_HEX 0x[0-9A-Fa-f]+ +NUMBER_DEC [0-9]+ +WHITESPACE [\t\n\r ] +COMMENT_START \/\* +COMMENT_END \*\/ + +%x COMMENT +%option yylineno +%% + +{COMMENT_START} BEGIN(COMMENT); + +{COMMENT_END} BEGIN(INITIAL); + +<> { + fprintf(stderr, "Kommentar nicht geschlossen\n"); + exit(1); +} + +(.|\n) /* alles im kommentar wird ignoriert */ + +struct return(STRUCT); +end return(END); +method return(METHOD); +var return(VAR); +if return(IF); +then return(THEN); +else return(ELSE); +while return(WHILE); +do return(DO); +return return(RETURN); +not return(NOT); +or return(OR); +this return(THIS); + +{IDENTIFIER} return(IDENT); @{ @IDENT.name@ = strdup(yytext); @} + +{NUMBER_DEC} return(NUM); +{NUMBER_HEX} return(NUM); + +\:= return(ASSIGN); +\; return(';'); +\( return('('); +\) return(')'); +\. return('.'); +\- return('-'); +\* return('*'); +\< return('<'); +\= return('='); +\, return(','); + +{WHITESPACE} /* ignore */ + +. { + fprintf(stderr, "Lexical error on line %i\n", yylineno); + exit(1); +} + +%% + diff --git a/codea/symtable.c b/codea/symtable.c new file mode 100755 index 0000000..850c1b0 --- /dev/null +++ b/codea/symtable.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include "symtable.h" + +#define DD + +struct symbol *tab_new(void) +{ + return SYMNULL; +} + +struct symbol *tab_clone(struct symbol *tab) +{ + struct symbol *elm = tab; + struct symbol *ntab = tab_new(); +#ifdef DD + printf("tab_clone: tab(%08X)\n", tab); +#endif + + while(elm != SYMNULL) { + ntab = tab_add_symbol(ntab, elm->ident, elm->type, 0); + elm = elm->next; + } + return ntab; +} + +struct symbol *tab_add_symbol(struct symbol *tab, char *ident, short type, short check) +{ + struct symbol *elm = tab; + struct symbol *new_elm; +#ifdef DD + printf("tab_add_symbol: tab(%08X), ident(%s), type(%i), check(%i)\n", tab, ident, type, check); +#endif + + if(tab_lookup(tab, ident, type) != SYMNULL) { + if(check) { + fprintf(stderr, "Identifier doppelt vorhanden: \"%s\"\n", ident); + exit(3); + } else { + tab = tab_remove_symbol(tab, ident, type); + } + } + + new_elm = (struct symbol *) malloc(sizeof(struct symbol)); + new_elm->next = SYMNULL; + new_elm->ident = strdup(ident); + new_elm->type = type; + + if(tab == SYMNULL) { + return new_elm; + } + + while(elm->next != SYMNULL) { + elm = elm->next; + } + elm->next = new_elm; + + return tab; +} + +struct symbol *tab_lookup(struct symbol *tab, char *ident, short type) +{ + struct symbol *elm = tab; + + if(tab == SYMNULL) { + return SYMNULL; + } + + do { + if((elm->type == type) && (strcmp(elm->ident, ident) == 0)) { + return elm; + } + elm = elm->next; + } while(elm != SYMNULL); + + return SYMNULL; +} + +struct symbol *tab_merge(struct symbol *tab, struct symbol *to_add, short check) +{ + struct symbol *elm = to_add; + struct symbol *ntab = tab_clone(tab); +#ifdef DD + printf("tab_merge: tab(%08X), to_add(%08X), check(%i), ntab(%08X)\n", tab, to_add, check, ntab); +#endif + + while(elm != SYMNULL) { + ntab = tab_add_symbol(ntab, elm->ident, elm->type, check); + elm = elm->next; + } + + return ntab; +} + +struct symbol *tab_remove_symbol(struct symbol *tab, char *ident, short type) +{ + struct symbol *elm = tab; + struct symbol *previous_elm = SYMNULL; + + while(elm != SYMNULL) { + if((elm->type == type) && (strcmp(elm->ident, ident) == 0)) { + if(previous_elm == SYMNULL) { + tab = elm->next; + } else { + previous_elm->next = elm->next; + } + (void)free(elm->ident); + (void)free(elm); + break; + } + previous_elm = elm; + elm = elm->next; + } + + return tab; +} + +void check(struct symbol *tab, char *ident, short type) +{ + struct symbol *elm; +#ifdef DD + printf("check: tab(%08X), ident(%s), type(%i), elm(%08X)\n", tab, ident, type, elm); +#endif + + if(type == S_VAR) { + elm = tab_lookup(tab, ident, type); + if(elm != SYMNULL) { + return; + } + } + + /* keine passende variable gefunden? + * => vllt gibt es ja ein passenden feldnamen */ + elm = tab_lookup(tab, ident, S_FIELD); + if(elm == SYMNULL) { + fprintf(stderr, "Unbekannter Identifier: \"%s\"\n", ident); + exit(3); + } +} + diff --git a/codea/symtable.h b/codea/symtable.h new file mode 100755 index 0000000..df7fa5a --- /dev/null +++ b/codea/symtable.h @@ -0,0 +1,23 @@ +#ifndef SYMTABLE_H +#define SYMTABLE_H + +#define S_FIELD 0 +#define S_VAR 1 + +#define SYMNULL (struct symbol *)NULL + +struct symbol { + char *ident; + struct symbol *next; + short type; +}; + +struct symbol *tab_clone(struct symbol *tab); +struct symbol *tab_new(void); +struct symbol *tab_add_symbol(struct symbol *tab, char *ident, short type, short check); +struct symbol *tab_lookup(struct symbol *tab, char *ident, short type); +struct symbol *tab_remove_symbol(struct symbol *tab, char *ident, short type); +struct symbol *tab_merge(struct symbol *tab, struct symbol *to_add, short check); +void check(struct symbol *tab, char *ident, short type); + +#endif -- 2.25.1