codea: init
authorBernhard Urban <lewurm@gmail.com>
Thu, 22 Apr 2010 13:24:08 +0000 (15:24 +0200)
committerBernhard Urban <lewurm@gmail.com>
Thu, 22 Apr 2010 13:24:08 +0000 (15:24 +0200)
.gitignore
codea/Makefile [new file with mode: 0644]
codea/code.bfe [new file with mode: 0644]
codea/parser.y [new file with mode: 0644]
codea/scanner.lex [new file with mode: 0644]
codea/symtable.c [new file with mode: 0755]
codea/symtable.h [new file with mode: 0755]

index 518f397afc165e6f5f6a0993a6c64f6c90f98873..300bf9d82ba07f6e59988195d62c6777fd0cf664 100644 (file)
@@ -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 (file)
index 0000000..840aa1b
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/codea/parser.y b/codea/parser.y
new file mode 100644 (file)
index 0000000..dbd4e24
--- /dev/null
@@ -0,0 +1,231 @@
+%{
+       #include <stdio.h>
+       #include <stdlib.h>
+       #include <string.h>
+       #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 (file)
index 0000000..c104d0f
--- /dev/null
@@ -0,0 +1,67 @@
+       #include <stdio.h>
+       #include <stdlib.h>
+       #include <string.h>
+       #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>{COMMENT_END} BEGIN(INITIAL);
+
+<COMMENT><<EOF>> {
+       fprintf(stderr, "Kommentar nicht geschlossen\n");
+       exit(1);
+}
+
+<COMMENT>(.|\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 (executable)
index 0000000..850c1b0
--- /dev/null
@@ -0,0 +1,141 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#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 (executable)
index 0000000..df7fa5a
--- /dev/null
@@ -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