Commits

Radomir Dopieralski committed ff5e493 Draft

2003-01-29

  • Participants
  • Parent commits 1361f21

Comments (0)

Files changed (52)

 # Makefile for PasAna
 
-YACC=bison -v -d
+YACC=bison -d
+LEX = flex
 CC=gcc
 RM= rm -f
 
-OBJS=tp4.tab.o tokenize.o dict.o parser.o
+OBJS=pascal.tab.o utils.o parser.o symbols.o pascal.yy.o main.o keywords.o node_new.o codetext.o codetools.o codenodes.o view.o write.o
 PROG=pasana
 
 GLIB_CFLAGS=`glib-config --cflags`
 GLIB_LIBS=`glib-config --libs`
 
-CFLAGS= -ggdb -Wall $(GLIB_CFLAGS) -DDEBUG
-LIBS=$(GLIB_LIBS)
-INCS=-I./
+CFLAGS= -ggdb -Wall --pedantic $(GLIB_CFLAGS) #-DDEBUG
+LIBS=$(GLIB_LIBS) -lncurses
+INCS=-I./ -I/usr/include/ncurses/
 
 prog: $(OBJS)
 	$(CC) $(LIBS) $(OBJS) -o $(PROG)
 
-test: test_token sample.pas
-	./test_token
+test: $(PROG) sample.pas
+	./$(PROG) sample.pas
 
 clean:
-	$(RM) tp4.tab.c tp4.tab.h
+	$(RM) pascal.tab.c pascal.tab.h pascal.yy.c pascal.output
 	$(RM) $(OBJS)
 	$(RM) $(PROG)
-	$(RM) test_token token_test.o
 
-tp4.tab.c: tp4.y
-	$(YACC) tp4.y
+pasana:	prog
 
-tp4.tab.h: tp4.y
-	$(YACC) tp4.y
+pascal.tab.c: pascal.y
+	$(YACC) pascal.y
+
+pascal.tab.h: pascal.y
+	$(YACC) pascal.y
+
+pascal.yy.c: pascal.l
+	$(LEX) -opascal.yy.c pascal.l
 
 .c.o: $*.c
 	$(CC) $(CFLAGS) $(INCS) -c $*.c -o $@
 
-test_token: token_test.o tokenize.o
-	$(CC) $(LIBS) $^ -o $@
-
-dict.o: dict.c dict.h tp4.tab.h
-dict_test.o: dict_test.c dict.h
-parser.o: parser.c dict.h tokenize.h tp4.tab.h parser.h
-tokenize.o: tokenize.c tokenize.h
-token_test.o: token_test.c tokenize.h
-tp4.tab.o: tp4.tab.c parser.h
+codenodes.o: codenodes.c symbols.h node.h codetext.h codetools.h \
+ codenodes.h pascal.tab.h
+codetext.o: codetext.c codetext.h node.h symbols.h
+codetools.o: codetools.c codetools.h codetext.h node.h symbols.h
+keywords.o: keywords.c parser.h node.h symbols.h pascal.tab.h
+main.o: main.c parser.h node.h symbols.h codetext.h codetools.h \
+ codenodes.h view.h
+node_new.o: node_new.c node.h symbols.h node_new.h parser.h \
+ pascal.tab.h
+parser.o: parser.c symbols.h parser.h node.h keywords.h
+pascal.tab.o: pascal.tab.c symbols.h node.h node_new.h parser.h \
+ keywords.h utils.h
+pascal.yy.o: pascal.yy.c parser.h node.h symbols.h keywords.h \
+ pascal.tab.h utils.h
+symbols.o: symbols.c symbols.h node.h
+utils.o: utils.c symbols.h parser.h node.h utils.h
+view.o: view.c view.h codetext.h node.h symbols.h
+write.o: write.c write.h codetext.h node.h symbols.h
+/* Zestaw procedur do zamieniania na tekst roznych rodzajow wezlow. */
+
+#include <glib.h>
+#include "symbols.h"
+#include "node.h"
+#include "codetext.h"
+#include "codetools.h"
+#include "codenodes.h"
+#include "pascal.tab.h"
+
+void printNamespace(CodeText *text, Namespace *nam);
+
+/* Wy�wietla dany symbol (nazw�) lub jego zawarto��, je�li nie ma nazwy. */
+void
+printSymbolNode(CodeText *text, SymbolNode * node)
+{
+    if (node == NULL)
+        return;
+
+    if (node->parent != NULL) {
+        switch (node->kind) {
+            case SYM_TYPE_POINTER:
+            case SYM_TYPE_STRING:
+            case SYM_TYPE_ARRAY:
+            case SYM_TYPE_SET:
+            case SYM_TYPE_SUBRANGE:
+            case SYM_TYPE_ENUM:
+            case SYM_TYPE_RECORD:
+            case SYM_TYPE_FILE:
+                codeBeginTag(text, HG_TYPE, node);
+                break;
+            case SYM_LABEL:
+                codeBeginTag(text, HG_LABEL, node);
+                break;
+            case SYM_CONST:
+                codeBeginTag(text, HG_CONST, node);
+                break;
+            default:
+                codeBeginTag(text, HG_IDENT, node);
+        }
+        codePrint(text, node->name->str);
+        codeEndTag(text);
+    } else {
+        printSymbolNodeContents(text, node);
+    }
+
+}
+
+/* Wy�wietla tre�� danego symbolu. */
+void
+printSymbolNodeContents(CodeText *text, SymbolNode * node)
+{
+    GList          *iter;
+
+    if (node == NULL)
+        return;
+
+    switch (node->kind) {
+        case SYM_TAG_FIELD:
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data!=NULL) {
+                    printExprNode(text, iter->data);
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ";");
+                    codeEndTag(text);
+                    codeNewLine(text);
+                }
+            }
+            break;
+        case SYM_TYPE_POINTER:
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "^");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_TYPE_STRING:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "STRING");
+            codeEndTag(text);
+            if (node->expr != NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, "[");
+                codeEndTag(text);
+                printExprNode(text, node->expr);
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, "]");
+                codeEndTag(text);
+            }
+            break;
+        case SYM_TYPE_ARRAY:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "ARRAY");
+            codeEndTag(text);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "[");
+            codeEndTag(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                printSymbolNode(text, iter->data);
+                if (iter->next != NULL) {
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ", ");
+                    codeEndTag(text);
+                }
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "] ");
+            codeEndTag(text);
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "OF ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_TYPE_SET:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "SET OF ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_TYPE_SUBRANGE:
+            printExprNode(text, node->expr);
+            break;
+        case SYM_TYPE_ENUM:
+            codePrint(text, "enumeraton");
+            break;
+        case SYM_TYPE_RECORD:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "RECORD");
+            codeEndTag(text);
+            codeNewLine(text);
+            codeIndent(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data!=NULL) {
+                    printSymbolNodeDef(text, iter->data);
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ";");
+                    codeEndTag(text);
+                    codeNewLine(text);
+                }
+            }
+            /* printNamespace(text, node->symbols); */
+            printSymbolNodeDef(text, node->base);
+            codeUnindent(text);
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "END");
+            codeEndTag(text);
+            break;
+        case SYM_TYPE_FILE:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "FILE OF ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_VAR_LOCAL:
+        case SYM_VAR_PARAM:
+        case SYM_VAR_VARPARAM:
+        case SYM_VAR_DEARR:
+        case SYM_VAR_DEREF:
+        case SYM_VAR_CAST:
+        case SYM_UNIT:
+            printSymbolNode(text, node);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            break;
+        case SYM_LABEL:
+            printSymbolNode(text, node);
+#if 0
+            codeBeginTag(text, HG_LABEL, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            break;
+        case SYM_CONST:
+            printSymbolNode(text, node);
+#if 0
+            codeBeginTag(text, HG_CONST, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            break;
+        case SYM_VAR_FIELD:
+            if (node->base == node) {
+                codeBeginTag(text, HG_IDENT, node);
+                codePrint(text, node->name->str);
+                codeEndTag(text);
+            } else {
+                printSymbolNode(text, node->base);
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ".");
+                codeEndTag(text);
+                codeBeginTag(text, HG_IDENT, node);
+                codePrint(text, node->name->str);
+                codeEndTag(text);
+            }
+            break;
+        case SYM_PROC:
+        case SYM_FUNC:
+            codeIndent(text);
+            printNamespace(text, node->symbols);
+            printStmtNode(text, node->stmt);
+            codeUnindent(text);
+            break;
+        case SYM_PROG:
+            codeIndent(text);
+            printNamespace(text, node->symbols);
+
+            printStmtNode(text, node->stmt);
+            codeUnindent(text);
+            break;
+        default:
+            codeBeginTag(text, HG_ERROR, NULL);
+            codePrint(text, "?symbol?");
+            codeEndTag(text);
+    }
+}
+
+/* Wy�wietla definicj� danego symbolu. */
+void
+printSymbolNodeDef(CodeText *text, SymbolNode * node)
+{
+    GList          *iter;
+
+    if (node == NULL)
+        return;
+
+    if (node->bcomm != NULL) {
+        codeBeginTag(text, HG_COMMENT, NULL);
+        codePrint(text, node->bcomm->str);
+        codeEndTag(text);
+        codeNewLine(text);   
+    }
+
+    if (node->ccomm!=NULL) {
+        codeComment(text, node->ccomm->str);
+    }
+
+    switch (node->kind) {
+        case SYM_TAG_FIELD:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "CASE ");
+            codeEndTag(text);
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+            if (node->type!=NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ": ");
+                codeEndTag(text);
+                printSymbolNode(text, node->type);
+            }
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, " OF");
+            codeEndTag(text);
+            codeNewLine(text);
+            codeIndent(text);
+            printSymbolNodeContents(text, node);
+            codeUnindent(text);
+            break;
+        case SYM_TYPE_POINTER:
+        case SYM_TYPE_STRING:
+        case SYM_TYPE_ARRAY:
+        case SYM_TYPE_SET:
+        case SYM_TYPE_SUBRANGE:
+        case SYM_TYPE_ENUM:
+        case SYM_TYPE_RECORD:
+        case SYM_TYPE_FILE:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "TYPE ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, " = ");
+            codeEndTag(text);
+            printSymbolNodeContents(text, node);
+            break;
+        case SYM_VAR_PARAM:
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str); 
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ": ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_VAR_VARPARAM:
+            codeBeginTag(text, HG_TYPE, NULL);
+            codePrint(text, "VAR ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            if (node->type!=NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ": ");
+                codeEndTag(text);
+                printSymbolNode(text, node->type);
+            }
+            break;
+        case SYM_VAR_LOCAL:
+        case SYM_VAR_DEARR:
+        case SYM_VAR_DEREF:
+        case SYM_VAR_CAST:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "VAR ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ": ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_VAR_FIELD:
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data != NULL) {
+                    printExprNode(text, iter->data);
+                }
+                codeBeginTag(text, HG_PUNCT, NULL);
+                if (iter->next != NULL) {
+                    codePrint(text, ", ");
+                } else {
+                    codePrint(text, ": ");
+                }
+                codeEndTag(text);
+            }
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ": ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            break;
+        case SYM_LABEL:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "LABEL ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_LABEL, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            break;
+        case SYM_PROC:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "PROCEDURE ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            if (node->list != NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, "(");
+                codeEndTag(text);
+                for (iter = node->list; iter != NULL; iter = iter->next) {
+                    printSymbolNodeDef(text, iter->data);
+                    if (iter->next != NULL) {
+                        codeBeginTag(text, HG_PUNCT, NULL);
+                        codePrint(text, "; ");
+                        codeEndTag(text);
+                    }
+                }
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ")");
+                codeEndTag(text);
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ";");
+            codeEndTag(text);
+            codeNewLine(text);
+            printSymbolNodeContents(text, node);
+            break;
+        case SYM_FUNC:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "FUNCTION ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            if (node->list != NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, "(");
+                codeEndTag(text);
+                for (iter = node->list; iter != NULL; iter = iter->next) {
+                    node = ((SymbolNode *) iter->data);
+                    printSymbolNodeDef(text, node);
+                    if (iter->next != NULL) {
+                        codeBeginTag(text, HG_PUNCT, NULL);
+                        codePrint(text, "; ");
+                        codeEndTag(text);
+                    }
+                }
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ")");
+                codeEndTag(text);
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ": ");
+            codeEndTag(text);
+            printSymbolNode(text, node->type);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ";");
+            codeEndTag(text);
+            codeNewLine(text);
+            printSymbolNodeContents(text, node);
+            break;
+        case SYM_CONST:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "CONST ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_CONST, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            if (node->type != NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ": ");
+                codeEndTag(text);
+                printSymbolNode(text, node->type);
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, " = ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            break;
+        case SYM_UNIT:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "USES ");
+            codeEndTag(text);
+#if 0
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+#endif
+            printSymbolNode(text, node);
+            break;
+        case SYM_PROG:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "PROGRAM ");
+            codeEndTag(text);
+            codeBeginTag(text, HG_IDENT, node);
+            codePrint(text, node->name->str);
+            codeEndTag(text);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "(");
+            codeEndTag(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                codePrint(text, (char *)(iter->data));
+                if (iter->next != NULL) {
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ", ");
+                    codeEndTag(text);
+                }
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ");");
+            codeEndTag(text);
+            codeNewLine(text);
+            printSymbolNodeContents(text, node);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ".");
+            codeEndTag(text);
+            break;
+        default:
+            codeBeginTag(text, HG_ERROR, NULL);
+            codePrint(text, "?symbol?");
+            codeEndTag(text);
+    }
+}
+
+/* Wy�wietla w�ze� rozkazu. */
+void
+printStmtNode(CodeText *text, StmtNode * node)
+{
+    GList          *iter;
+
+    if (node == NULL)
+        return;
+
+    if (node->bcomm != NULL) {
+        codeBeginTag(text, HG_COMMENT, NULL);
+        codePrint(text, node->bcomm->str);
+        codeEndTag(text);
+        codeNewLine(text);   
+    }
+
+    if (node->label!=NULL) {
+        codeLabel(text, node->label->name->str);
+        codeLabel(text, ": ");
+    }
+    
+    if (node->ccomm!=NULL) {
+        codeComment(text, node->ccomm->str);
+    }
+
+    switch (node->kind) {
+        case STMT_CASE_CASE:
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                printExprNode(text, iter->data);
+                if (iter->next != NULL) {
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ", ");
+                    codeEndTag(text);
+                }
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ": ");
+            codeEndTag(text);
+            printStmtNode(text, node->stmt);
+            break;
+        case STMT_CASE_HEAD:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "CASE ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " OF");
+            codeEndTag(text);
+            codeNewLine(text);
+            codeIndent(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data != NULL) {
+                    printStmtNode(text, iter->data);
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ";");
+                    codeEndTag(text);
+                    codeNewLine(text);
+                }
+            }
+            if (node->stmt != NULL) {
+                codeBeginTag(text, HG_KEYWORD, NULL);
+                codePrint(text, "ELSE ");
+                codeEndTag(text);
+                printStmtNode(text, node->stmt);
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ";");
+                codeEndTag(text);
+                codeNewLine(text);
+            }
+            codeUnindent(text);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "END");
+            codeEndTag(text);
+            break;
+        case STMT_REPEAT:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "REPEAT");
+            codeEndTag(text);
+            codeNewLine(text);
+            codeIndent(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                printStmtNode(text, iter->data);
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ";");
+                codeEndTag(text);
+                codeNewLine(text);
+            }
+            codeUnindent(text);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "UNTIL ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            break;
+        case STMT_WHILE:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "WHILE ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " DO ");
+            codeEndTag(text);
+            printStmtNode(text, node->stmt);
+            break;
+        case STMT_WITH:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "WITH ");
+            codeEndTag(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data != NULL) {
+                    printSymbolNode(text, (SymbolNode *)iter->data);
+                    if (iter->next != NULL) {
+                        codeBeginTag(text, HG_PUNCT, NULL);
+                        codePrint(text, ", ");
+                        codeEndTag(text);
+                    }
+                }
+            }
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " DO ");
+            codeEndTag(text);
+            printStmtNode(text, node->stmt);
+            break;
+        case STMT_GOTO:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "GOTO ");
+            codeEndTag(text);
+            printSymbolNode(text, node->symbol);
+            break;
+        case STMT_BLOCK:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "BEGIN");
+            codeEndTag(text);
+            codeNewLine(text);
+            codeIndent(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data != NULL) {
+                    printStmtNode(text, iter->data);
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ";");
+                    codeEndTag(text);
+                    codeNewLine(text);
+                }
+            }
+            codeUnindent(text);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "END");
+            codeEndTag(text);
+            break;
+        case STMT_IF:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "IF ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " THEN ");
+            codeEndTag(text);
+            printStmtNode(text, node->stmt);
+            if (node->stmt2 != NULL) {
+                codeBeginTag(text, HG_KEYWORD, NULL);
+                codePrint(text, " ELSE ");
+                codeEndTag(text);
+                printStmtNode(text, node->stmt2);
+            }
+            break;
+        case STMT_ASSIGN:
+            printSymbolNode(text, node->symbol);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ":= ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            break;
+        case STMT_PROC:
+            printSymbolNode(text, node->symbol);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "(");
+            codeEndTag(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                printExprNode(text, iter->data);
+                if (iter->next != NULL) {
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ", ");
+                    codeEndTag(text);
+                }
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ")");
+            codeEndTag(text);
+            break;
+        case STMT_FOR:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "FOR ");
+            codeEndTag(text);
+            printSymbolNode(text, node->symbol);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ":= ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " TO ");
+            codeEndTag(text);
+            printExprNode(text, node->expr2);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " DO ");
+            codeEndTag(text);
+            printStmtNode(text, node->stmt);
+            break;
+        case STMT_FOR_DOWN:
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, "FOR ");
+            codeEndTag(text);
+            printSymbolNode(text, node->symbol);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ":= ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " DOWNTO ");
+            codeEndTag(text);
+            printExprNode(text, node->expr2);
+            codeBeginTag(text, HG_KEYWORD, NULL);
+            codePrint(text, " DO ");
+            codeEndTag(text);
+            printStmtNode(text, node->stmt);
+            break;
+        default:
+            codeBeginTag(text, HG_ERROR, NULL);
+            codePrint(text, "?stmt?");
+            codeEndTag(text);
+    }
+}
+
+const char     *
+getOper(enum OperKind oper)
+{
+    switch (oper) {
+        case OPER_PLUS:
+            return "+";
+        case OPER_MINUS:
+            return "-";
+        case OPER_STAR:
+            return "*";
+        case OPER_SLASH:
+            return "/";
+        case OPER_DIV:
+            return "DIV";
+        case OPER_MOD:
+            return "MOD";
+        case OPER_SHL:
+            return "SHL";
+        case OPER_SHR:
+            return "SHR";
+        case OPER_EQ:
+            return "=";
+        case OPER_NEQ:
+            return "<>";
+        case OPER_GT:
+            return ">";
+        case OPER_LT:
+            return "<";
+        case OPER_GEQ:
+            return ">=";
+        case OPER_LEQ:
+            return "<=";
+        case OPER_IN:
+            return "IN";
+        case OPER_XOR:
+            return "XOR";
+        case OPER_OR:
+            return "OR";
+        case OPER_AND:
+            return "AND";
+        case OPER_NOT:
+            return "NOT";
+        case OPER_NONE:
+        default:
+            return " ";
+
+    }
+}
+
+void
+printExprNode(CodeText *text, ExprNode * node)
+{
+    GList          *iter;
+
+    if (node == NULL)
+        return;
+
+    switch (node->kind) {
+        case EXPR_VARIANT:
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text,"(");
+            codeEndTag(text);
+            codeIndent(text);
+            codeNewLine(text);
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                if (iter->data!=NULL) {
+                    printSymbolNodeDef(text, iter->data);
+                    codeBeginTag(text, HG_PUNCT, NULL);
+                    codePrint(text, ";");
+                    codeEndTag(text);
+                    codeNewLine(text);
+                }
+            }
+            printSymbolNodeDef(text, node->symbol);
+            codeUnindent(text);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text,")");
+            codeEndTag(text);
+            break;
+        case EXPR_CASES:
+            for (iter = node->list; iter != NULL; iter = iter->next) {
+                printExprNode(text, iter->data);
+                codeBeginTag(text, HG_PUNCT, NULL);
+                if (iter->next != NULL)
+                    codePrint(text, ", ");
+                else
+                    codePrint(text, ": ");
+                codeEndTag(text);
+            }
+            break;
+        case EXPR_ADDR:
+            if (node->symbol != NULL) {
+                codePrint(text, "@");
+                printSymbolNode(text, node->symbol);
+            } else {
+                printExprNode(text, node->expr);
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ":");
+                codeEndTag(text);
+                printExprNode(text, node->expr2);
+            }
+            break;
+        case EXPR_NUMBER:
+            codeBeginTag(text, HG_NUMBER, node);
+            codePrint(text, node->value->str);
+            codeEndTag(text);
+            break;
+        case EXPR_STRING:
+            codeBeginTag(text, HG_STRING, node);
+            codePrint(text, node->value->str);
+            codeEndTag(text);
+            break;
+        case EXPR_CONST:
+        case EXPR_VAR:
+            printSymbolNode(text, node->symbol);
+            break;
+        case EXPR_PAREN:
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "( ");
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, " )");
+            codeEndTag(text);
+            break;
+        case EXPR_UN:
+            codeBeginTag(text, HG_OPER, node);
+            codePrint(text, getOper(node->oper));
+            codeEndTag(text);
+            printExprNode(text, node->expr);
+            break;
+        case EXPR_BIN:
+        case EXPR_EQ:
+            printExprNode(text, node->expr);
+            codePrint(text, " ");
+            codeBeginTag(text, HG_OPER, node);
+            codePrint(text, getOper(node->oper));
+            codeEndTag(text);
+            codePrint(text, " ");
+            printExprNode(text, node->expr2);
+            break;
+        case EXPR_SET:
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "[");
+            codeEndTag(text);
+            if (node->list != NULL) {
+                for (iter = node->list; iter != NULL; iter = iter->next) {
+                    printExprNode(text, iter->data);
+                    if (iter->next != NULL) {
+                        codeBeginTag(text, HG_PUNCT, NULL);
+                        codePrint(text, ", ");
+                        codeEndTag(text);
+                    }
+                }
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "]");
+            codeEndTag(text);
+            break;
+        case EXPR_ARRAY:
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "(");
+            codeEndTag(text);
+            if (node->list != NULL) {
+                for (iter = node->list; iter != NULL; iter = iter->next) {
+                    printExprNode(text, iter->data);
+                    if (iter->next != NULL) {
+                        codeBeginTag(text, HG_PUNCT, NULL);
+                        codePrint(text, ", ");
+                        codeEndTag(text);
+                    }
+                }
+            }
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ")");
+            codeEndTag(text);
+            break;
+        case EXPR_NIL:
+            codeBeginTag(text, HG_CONST, node);
+            codePrint(text, "NIL");
+            codeEndTag(text);
+            break;
+        case EXPR_RANGE:
+            printExprNode(text, node->expr);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, "..");
+            codeEndTag(text);
+            printExprNode(text, node->expr2);
+            break;
+        case EXPR_FUNC:
+            printSymbolNode(text, node->symbol);
+            if (node->list != NULL) {
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, "(");
+                codeEndTag(text);
+                for (iter = node->list; iter != NULL; iter = iter->next) {
+                    printExprNode(text, iter->data);
+                    if (iter->next != NULL) {
+                        codeBeginTag(text, HG_PUNCT, NULL);
+                        codePrint(text, ", ");
+                        codeEndTag(text);
+                    }
+                }
+                codeBeginTag(text, HG_PUNCT, NULL);
+                codePrint(text, ")");
+                codeEndTag(text);
+            }
+        default:
+            codeBeginTag(text, HG_ERROR, NULL);
+            codePrint(text, "?expr?");
+            codeEndTag(text);
+    }
+}
+
+void
+printNamespace(CodeText *text, Namespace * nam)
+{
+    GList          *iter;
+    SymbolNode     *node;
+
+    if (nam == NULL)
+        return;
+    for (iter = nam->list; iter != NULL; iter = iter->next) {
+        node = ((SymbolNode *) iter->data);
+        if ((node->kind != SYM_VAR_PARAM) && (node->kind != SYM_VAR_VARPARAM)) {
+            printSymbolNodeDef(text, node);
+            codeBeginTag(text, HG_PUNCT, NULL);
+            codePrint(text, ";");
+            codeEndTag(text);
+            codeNewLine(text);
+        }
+    }
+}
+/* Procedury do wyswietlania informacji o wezlach. */
+
+#ifndef CODENODES_H
+#define CODENODES_H
+
+#include "node.h"
+#include "codetext.h"
+
+
+/* Wy�wietla symbol. */
+void printSymbolNode(CodeText *text, SymbolNode *node);
+
+/* Wy�wietla definicj� danego symbolu. */
+void printSymbolNodeDef(CodeText *text, SymbolNode *node);
+
+/* Wy�wietla tre�� danego symbolu. */
+void printSymbolNodeContents(CodeText *text, SymbolNode *node);
+
+/* Wy�wietla w�ze� rozkazu. */
+void printStmtNode(CodeText *text, StmtNode *node);
+
+void printExprNode(CodeText *text, ExprNode *node);
+
+#endif /* not CODENODES_H */
+
+#include <glib.h>
+#include "codetext.h"
+
+/* Tworzy nowy obiekt CodeLIne. */
+CodeLine*
+newCodeLine(CodeText *text)
+{
+    CodeLine *line;
+    
+    line = g_new(CodeLine, 1);
+    line->string = g_string_new("");
+    line->comment = NULL;
+    line->tag_list = NULL;
+    line->label = NULL;
+    line->indent = 0;
+    line->number = ++(text->line_no);
+    return line;
+}
+
+/* Tworzy nowy obiekt CodeTag. */
+CodeTag*
+newCodeTag()
+{
+    CodeTag *tag;
+
+    tag = g_new(CodeTag, 1);
+    tag->group = HG_TEXT;
+    tag->xstart = 0;
+    tag->ystart = 0;
+    tag->xend = 0;
+    tag->yend = 0;
+    tag->node = NULL;
+    return tag;
+}
+
+/* Tworzy nowy obiekt CodeText. */
+CodeText*
+newCodeText()
+{
+    CodeText *text;
+
+    text = g_new(CodeText, 1);
+    text->line_list = NULL;
+    text->tag_stack= NULL;
+    text->last_line = NULL;
+    text->line_no = 0;
+    text->indent = 0;
+    return text;
+}
+/* Definicja typu trzymaj�cego tekst kodu programu. */
+
+#ifndef CODETEXT_H
+#define CODETEXT_H
+
+#include <glib.h>
+#include "node.h"
+
+/* Grupy wyrozniania (do kolorowania) */
+enum HiGroup {
+    HG_TEXT,
+    HG_KEYWORD,
+    HG_TYPE,
+    HG_IDENT,
+    HG_OPER,
+    HG_CONST,
+    HG_STRING,
+    HG_COMMENT,
+    HG_LABEL,
+    HG_LINENO,
+    HG_PUNCT,
+    HG_NUMBER,
+    HG_ERROR,
+    HG_MAXIMUM
+};
+
+/* Pojedy�cza linijka kodu. */
+struct CodeLine {
+    int             indent;                                /* Wci�cie danej linijki. */
+    int             number;                                /* Numer linii. */
+    GString        *string;                                /* Tekst kodu do wy�wietlenia. */
+    GString        *comment;                               /* Komentarz do wy�wietlenia. */
+    GString        *label;                                 /* Etykieta. */
+    GList          *tag_list;                                /* Lista informacji o tokenach. */
+};
+typedef struct CodeLine CodeLine;
+
+/* Informacja o jednym tokenie. */
+struct CodeTag {
+    int             xstart, ystart, xend, yend;            /* Odk�d dok�d si� ci�gnie. */
+    enum HiGroup    group;                                 /* Jak ma byc kolorowany? */
+    void           *node;                                  /* Wska�nik do danego w�z�a. */
+};
+typedef struct CodeTag CodeTag;
+
+/* Ca�y kod programu. */
+struct CodeText {
+    GList          *line_list;                             /* Poszczeg�lne linijki kodu. */
+    CodeLine       *last_line;                             /* Ostatnio dodana linia (bierzaca). */
+    int             indent;                                /* Wci�cie jakie nale�y zastosowa� do nowych linijek. */
+    int             line_no;                               /* Ilosc linii. */
+    GList          *tag_stack;                             /* Stos token�w do kontroli ich ko�czenia si�. */
+};
+typedef struct CodeText CodeText;
+
+/* Tworzy nowy obiekt CodeLIne. */
+CodeLine       *newCodeLine(CodeText * text);
+
+/* Tworzy nowy obiekt CodeTag. */
+CodeTag      *newCodeTag();
+
+/* Tworzy nowy obiekt CodeText. */
+CodeText       *newCodeText();
+#endif                                                     /* not CODETEXT_H */
+#include <stdio.h>
+#include "codetools.h"
+
+
+#define COMM_INDENT 60
+
+/* Zwi�ksza wci�cie kolejnych linii. */
+void
+codeIndent(CodeText *text)
+{
+    ++(text->indent);
+    if (text->last_line->string->len==0)
+        ++(text->last_line->indent);
+}
+
+/* Zmniejsza wci�cie. */
+void
+codeUnindent(CodeText *text)
+{
+    --(text->indent);
+    if (text->last_line->string->len==0)
+        --(text->last_line->indent);
+}
+
+/* Przechodzi do nowej linijki. */
+void
+codeNewLine(CodeText *text)
+{
+    CodeLine *line;
+
+    line = newCodeLine(text);
+    line->indent = text->indent;
+    text->last_line = line;
+    text->line_list = g_list_append(text->line_list, line);
+}
+
+/* Dodaje tekst do ostatniej linijki. */
+void
+codePrint(CodeText *text, const char *string)
+{
+    if (text->last_line == NULL)
+        codeNewLine(text);
+    text->last_line->string = g_string_append(text->last_line->string, string);
+}
+
+/* Dodaje tekst etykiety do ostatniej linijki. */
+void
+codeLabel(CodeText *text, const char *string)
+{
+    if (text->last_line == NULL)
+        codeNewLine(text);
+    if (text->last_line->label==NULL) {
+        text->last_line->label = g_string_new(string);
+    } else {
+        text->last_line->label = g_string_append(text->last_line->label, string);
+    }
+}
+
+/* Dodaje tekst komentarza do ostatniej linijki. */
+void
+codeComment(CodeText *text, const char *string)
+{
+    if (text->last_line == NULL)
+        codeNewLine(text);
+    if (text->last_line->comment==NULL) {
+        text->last_line->comment = g_string_new(string);
+    } else {
+        text->last_line->comment = g_string_append(text->last_line->comment, string);
+    }
+}
+
+/* Wy�wietla kod na ekranie. */
+void
+codeShow(CodeText *text)
+{
+    GList *iter;
+    CodeLine *line;
+    int ind;
+
+    if (text==NULL)
+        return;
+    for (iter=text->line_list; iter!=NULL; iter=iter->next) {
+        line = ((CodeLine *)iter->data);
+        if (line->label!=NULL) {
+            ind = line->label->len;
+            printf("%s", line->label->str);
+        } else {
+            ind = 0;
+        }
+        while (ind<line->indent*4) {
+            printf(" ");
+            ++ind;
+        }
+        printf("%s", line->string->str);
+        ind += line->string->len;
+        if (line->comment!=NULL) {
+            while (ind<COMM_INDENT) {
+                printf(" ");
+                ++ind;
+            }
+            printf("%s", line->comment->str);
+        }
+        printf("\n");
+    }
+}
+
+/* Zaznacza pocz�tek tokena. */
+void
+codeBeginTag(CodeText *text, int group, void *node)
+{
+    CodeTag *tag;
+    int kind;
+    
+    if (text->last_line == NULL)
+        codeNewLine(text);
+    tag = newCodeTag();
+    tag->xstart = text->last_line->string->len;
+    tag->ystart = (text->last_line->number)-1;
+    text->tag_stack = g_list_prepend(text->tag_stack, tag);    
+    text->last_line->tag_list = g_list_append(text->last_line->tag_list, tag);
+    tag->group = group;
+    tag->node = node;
+}
+
+/* Zanzacza koniec tokena. */
+void
+codeEndTag(CodeText *text)
+{
+    GList *first;
+    CodeTag *tag;
+
+    tag = text->tag_stack->data;
+    tag->xend = text->last_line->string->len;
+    tag->yend = (text->last_line->number)-1;
+    first = text->tag_stack;
+    text->tag_stack = g_list_remove_link(text->tag_stack, first);
+    g_list_free(first);
+}
+/* Procedury narz�dziowe do CodeText. */
+
+#ifndef CODETOOLS_H
+#define CODETOOLS_H
+
+#include "codetext.h"
+
+/* Zwi�ksza wci�cie kolejnych linii. */
+void codeIndent(CodeText *text);
+
+/* Zmniejsza wci�cie. */
+void codeUnindent(CodeText *text);
+
+/* Przechodzi do nowej linijki. */
+void codeNewLine(CodeText *text);
+
+/* Dodaje tekst do ostatniej linijki. */
+void codePrint(CodeText *text, const char *string);
+
+/* Wy�wietla kod na ekranie. */
+void codeShow(CodeText *text);
+
+/* Zaznacza pocz�tek tokena. */
+void codeBeginTag(CodeText *text, int group, void *node);
+
+/* Zanzacza koniec tokena. */
+void codeEndTag(CodeText *text);
+
+/* Dodaje tekst komentarza do ostatniej linijki. */
+void codeComment(CodeText *text, const char *string);
+
+/* Dodaje tekst etykiety do ostatniej linijki. */
+void codeLabel(CodeText *text, const char *string);
+
+#endif /* not CODETOOLS_H */

File dict.c

-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <glib.h>
-#include "dict.h"
-#include "tp4.tab.h"
-
-/* S�owa kluczowe s� globalne. */
-//static GHashTable *keywords_tab;
-
-Dictionary     *
-newDictionary()
-{
-    Dictionary     *dict;
-
-    dict = g_new(Dictionary, 1);
-    dict->table = g_hash_table_new(g_str_hash, g_str_equal);
-    dict->locals = g_hash_table_new(g_str_hash, g_str_equal);
-    return dict;
-}
-
-void
-dictAdd(Dictionary * dict, DictEntry * entry)
-{
-    int i;
-    
-    /* Wszystkie sybole z wielkich liter. */
-    for (i=0; entry->string[i]!='\0'; ++i)
-        entry->string[i] = toupper(entry->string[i]);
-    /* Sprawdzamy, czy taki symbol juz istnieje. */
-    if (g_hash_table_lookup(dict->table, entry->string) != NULL)
-        return;
-    g_hash_table_insert(dict->table, entry->string, entry);
-}
-
-void
-dictAddLocal(Dictionary * dict, DictEntry * entry)
-{
-    int i;
-    
-    /* Wszystkie sybole z wielkich liter. */
-    for (i=0; entry->string[i]!='\0'; ++i)
-        entry->string[i] = toupper(entry->string[i]);
-    /* Sprawdzamy, czy taki symbol juz istnieje. */
-    if (g_hash_table_lookup(dict->locals, entry->string) != NULL)
-        return;
-    g_hash_table_insert(dict->locals, entry->string, entry);
-}
-
-void
-keywordsInit(Dictionary *dict)
-{
-    int             i;
-    const static char *keywords_str[] =
-        {"AND", "ABSOLUTE", "ARRAY", "BEGIN", "CASE", "CONST", "DIV", "DOWNTO", "DO", "ELSE", "END",
-         "EXTERNAL", "FILE", "FORWARD", "FOR", "FUNCTION", "GOTO", "IF", "IMPLEMENTATION",
-         "INTERFACE", "IN", "LABEL", "MOD", "NIL", "NOT", "OF", "OR", "PACKED", "PROCEDURE",
-         "PROGRAM", "RECORD", "REPEAT", "SET", "SHL", "SHR", "STRING", "THEN", "TO", "TYPE", "UNIT",
-         "UNTIL", "USES", "VAR", "WHILE", "WITH", "XOR", "THEN", "ELSE", NULL};
-    const static int keywords_tok[] =
-        {K_AND, K_ABSOLUTE, K_ARRAY, K_BEGIN, K_CASE, K_CONST, K_DIV, K_DOWNTO, K_DO, K_ELSE, K_END,
-         K_EXTERNAL, K_FILE, K_FORWARD, K_FOR, K_FUNCTION, K_GOTO, K_IF, K_IMPLEMENTATION,
-         K_INTERFACE, K_IN, K_LABEL, K_MOD, K_NIL, K_NOT, K_OF, K_OR, K_PACKED, K_PROCEDURE,
-         K_PROGRAM, K_RECORD, K_REPEAT, K_SET, K_SHL, K_SHR, K_STRING, K_THEN, K_TO, K_TYPE, K_UNIT,
-         K_UNTIL, K_USES, K_VAR, K_WHILE, K_WITH, K_XOR, K_THEN, K_ELSE, 0};
-
-    dict->keywords = g_hash_table_new(g_str_hash, g_str_equal);
-    for (i = 0; keywords_str[i] != NULL; ++i) {
-        g_hash_table_insert(dict->keywords, (char *)(keywords_str[i]), GINT_TO_POINTER(keywords_tok[i]));
-    }
-}
-
-DictEntry *
-dictLookup(Dictionary * dict, const char *word)
-{
-    DictEntry      *entry;
-    char *upper;
-    int i;
-
-    upper = g_strdup(word);
-    for (i=0; upper[i]!='\0'; ++i)
-        upper[i] = toupper(upper[i]);
-    entry = g_hash_table_lookup(dict->locals, upper);
-    if (entry==NULL)
-        entry = g_hash_table_lookup(dict->table, upper);
-    else
-        printf("Local variable!\n");
-    g_free(upper);
-    return entry;
-}
-
-int
-keywordLookup(Dictionary *dict, const char *word)
-{
-    char *upper;
-    int i;
-    gpointer p;
-
-    upper = g_strdup(word);
-    for (i=0; upper[i]!='\0'; ++i)
-        upper[i] = toupper(upper[i]);
-    p = g_hash_table_lookup(dict->keywords, upper); 
-    g_free(upper);
-    if (p!=NULL)
-        return GPOINTER_TO_INT(p);
-    else
-        return 0;
-}

File dict.h

-/* Slownik i tablice symboli. */
-
-#ifndef DICT_H
-#define DICT_H
-
-struct Dictionary {
-    GHashTable     *locals;
-    GHashTable     *table;
-    GHashTable     *keywords;
-    /* Tu trzeba dodac rozne zakresy i inne takie. */
-};
-typedef struct Dictionary Dictionary;
-
-struct DictEntry {
-    char           *string;                                /* Do jakiego stringa to ma byc hashowane. */
-    int             token;                                 /* Rodzaj tokena do zwrocenia. */
-    /* ... XXX tu musi byc wiecej jeszcze */
-};
-typedef struct DictEntry DictEntry;
-
-/* Szukanie symbolu w slowniku. */
-DictEntry      *dictLookup(Dictionary * dict, const char *word);
-
-/* Wprowadzenie slow kluczowych. */
-void            keywordsInit(Dictionary * dict);
-
-/* Dodanie symbolu do slownika. */
-void            dictAdd(Dictionary * dict, DictEntry * entry);
-void            dictAddLocal(Dictionary * dict, DictEntry * entry);
-
-/* Wyszukiwanie slow kluczowych. */
-int             keywordLookup(Dictionary * dict, const char *word);
-
-/* Utworzenie nowego slownika. */
-Dictionary     *newDictionary();
-
-#endif

File docs/braki.txt

+Czego brakuje
+=============
+
+Parser obs�uguje sk�adnie Turbo Pascala w wersji 4.0 z pewnymi
+zastrze�eniami:
+
+Tak ju� zostanie (czego brakuje ale nie da si� ��two zrobi�):
+
+- Dodano cz�ciow� obs�ug� wyra�e� sta�ych z Turba Pascala 5.0 -- tylko
+  dla najprostrzych wyra�e�;
+- Brak obs�ugi wstawek w assemblerze (ASM...END) i procedur i funkcji
+  pisanych w assemblerze;
+- Brak obs�ugi dla zmiennych zdefiniowanych w konkretnym miejscu pami�ci;
+- Brak obs�ugi procedur typu INTERRUPT;
+- Brak typ�w proceduralnych -- pojawi�y sie w TP 5.0;
+- Komentarze nie s� formatowane;
+- Wszelkiego rodzaju sta�e nie s� formatowane -- pozostawiane s� w formie
+  w jakiej zosta�y zapisane (by� mo�e nawet niepoprawnej);
+- Procedury i funkcje wewn�trz procedur i funkcji -- jest to trywialne z
+  gramatycznego punktu widzenia, ale mo�e bardzo skomplikowa� analiz�
+  kodu. W�asno�� do rozwa�enia;
+
+Do poprawienia (co trzeba zrobi�):
+
+- Automatyczne wczytywanie symboli z unitu SYSTEM;
+- Obs�uga unit�w (wczytywanie z nich symboli);
+- Dodanie symboli ze standardowych unit�w;
+- Nie jest sprawdzana zgodno�� typ�w, ani nawet ilo�� parametr�w w
+  wywo�aniach funkcji i procedur;
+- Nie jest sparwdzana zgodno�� typ�w sta�ych;
+zrobione - Nie ma interface-u;
+zrobione - Kod jest wczytywany ze standardowego wej�cia -- nie ma obs�ugi plik�w;
+zrobione - Gramatyka zawiera jeden (niegro�ny) konflikt -- przy parsowaniu
+  nawias�w;
+- Nie s� liczone �adne metryki;
+zrobione - Zapisywanie sformatowanego kodu do pliku;
+- Przewijanie ekranu nie jest zwiazane z kursorem -- mozna nim wyjechac poza ekran.
+- W linii statusu nie sa wyswietlane informacje o wszystkich rodzajach wezlow.
+- Stale rekordowe nie sa poprawnie parsowane -- wymaga kontroli typow. (gramatyka
+  staje sie kontekstowa).
+
+Do zrobienia (mo�naby to zrobi�, ale chyba nie zd���, do zrobiena na PRP2):
+
+zrobione - Wy�wietlenie kolorowanego kodu;
+zarzucone - Wy�wietlenie drzewa parsowania z boku ekranu, a la explorer;
+- Zmiana nazwy danego symbolu we wszystkich miejscach w kodzie;
+- Edycja i dodawanie komentarzy;
+- Informowanie o nieu�ywanych symbolach;
+- Przesuwanie fragment�w kodu;
+- Sprawdzenie miejsc u�ycia symboli i sugerowanie zdefiniowania ich
+  lokalnie;
+- Sprawdzanie czytania i modyfikowania zmiennych przez polecenia;
+- Zmiana kolejno�ci polece� i definicji symboli bez zmiany dzia�ania
+  programu;
+- Konfiguracja zapisywana do pliku;
+- Sortowanie alfabetyczne definicji symboli;
+- Losowe przemieszczanie polece� bez zmiany dzia�ania programu;
+- Zmiana nazw symboli na losowe;
+- Zapisanie ca�ego programu w jednej linii, z losow� wielko�ci� liter w
+  s�owach kluczowych;
+- Wy�wietlenie grafu wywo�a� funkcji i procedur (bez cykli, specjalnie
+  oznaczone);
+- Automatyczne dodanie komentarzy;
+- Bardziej zaawansowane metryki programistyczne;
+- Eliminacja instrukcji WITH;
+- Sugerowanie wstawienia instrukcji WITH;
+- Formatowanie komentarzy;
+- Informowanie o niewykonywanych fragmentach kodu;
+- Sprawdzanie zakres�w warto�ci przyjmowanych przez wyra�enia;
+- Sugerowanie zmiany p�tli WHILE na REPEAT i odwrotnie;
+- Nazywanie symboli zgodnie z r�nymi konwencjami (czeska, s�owacka,
+  czechos�owacka, etc.);
+- System menu do wybierania plik�w do zapisu i odczytu;
+- Szacowanie z�o�ono�ci fragment�w programu (tylko n^a, po prostu liczenie
+  stopnia zagnie�d�enia p�tli);
+- Wyszukiwanie pewnych predefinowancyh fragment�w kodu i proponowanie
+  zamiany ich na r�wnowa�ne ale bardziej poz�dane (schematy wczytywane z
+  oddzielnego pliku);

File docs/manual.txt

+
+Pasana -- podrecznik uzytkownika.
+=================================
+
+1. Uruchamianie.
+----------------
+
+Program uruchamiamy, podajac mu jako pierwszy parametr nazwe pliku, ktory
+chcemy analizowac. Jesli plik nie znajduje sie w aktualnym katalogu, musimy
+podac do niego sciezke.
+
+Uruchomienie programu bez parametrow wyswietli krotka informacje o nim.
+
+2. Dzialanie.
+-------------
+
+Pasana parsuje podany plik z kodem zrodlowym, przeksztalca go na odpowiednie
+drzewo, a nastepnie wsyweitla je na ekranie ponownie w postaci kodu -- ale
+juz sformatowanego i pokolorowanego.
+Po zakonczeniu dzialania programu, sformatowany kod wypisywany jest do pliku
+'output.pas`.
+
+3. Obsluga.
+-----------
+
+W trakcie wysweitlania kodu mozemy uzyc nastepujacych klawiszy:
+
+strzalki -- wybieranie wezla drzewa (czyli elementu naszego programu). Nie wszystkie
+	wezly da sie wybrac -- kursor zatrzymuje sie tylko na najistotniejszych.
+pgup, pgdn -- przewijanie kodu programu o pol strony w gore i w dol.
+inne klawisze -- wyjscie z programu.
+
+4. Bledy.
+---------
+
+Program nie nadaje sie na walidator (w obecnym stadium) i nie `zauwaza' wielu bledow
+w kodzie. Jednak zauwazy bledy skladni -- wowczas wyswietla wlasciwy komentarz. Pierwsza
+linia to wygenerowany przez bison-a komunikat o bledzie, druga to dodana informacja
+o jego umiejscowieniu.

File docs/node.txt

+Wewn�trzna truktura drzewa parsowania
+=====================================
+
+
+W�z�y
+-----
+
+Mo�liwych jest kilka podej��. Najbardziej bezpo�rednim by�oby
+zdefiniowanie oddzielnej struktury danych dla ka�dej z produkcji gramatyki
+i przypisywanie symbolom powsta�ym z takiej produkcji takiej w�a�nie
+struktury danych jako warto��. Nie trzeba chyba wyja�nia�, �e takie
+podej�cie jest bardzo uci��liwe dla cz�owieka.
+
+Dlatego te� wybra�em pocz�tkowo inne podej�cie -- struktury danych
+tworzone s� tylko dla niekt�rych symboli nieterminalnych, a mianowicie
+tych, kt�re reprezentuj� pewne obiekty w sensie struktury programu, jak
+typy, zmienne, procedury, funkcje, polecenia, wyra�enia i tym podobne.
+Nadal jednak ka�de z nich mia�o swoj� oddzieln� struktur� danych.
+
+Ostatecznie zrezygnowa�em z takiego rozdzia�u. Podzieli�em zbi�r
+wszystkich rodzaj�w w�z��w na podzbiory o podobnych w�asno�ciach i dla
+ka�dego z tych podzbior�w zdefiniowa�em struktur� danych. Dodatkowe pole
+informuje o dok�adnym rodzaju danego w�z�a.
+
+I tak otrzyma�em 3 kategorie w�z�ow:
+
+1) Symbole -- czyli wszelkie obiekty posiadaj�ce nazw�, takie jak: typy,
+zmienne, sta�e nazwane, pola rekord�w, procedury, funkcje, unity, oraz sam
+program. Nie wszystkie jednak symbole koniecznie musz� mie� jak�� nazw� --
+dotyczy to g��wnie typ�w oraz niekt�rych zmiennych.
+
+2) Polecenia -- czyli pojedy�cze rozkazy programu, takie jak: blok,
+instrukcja skoku, instrukcja warunkowa, p�tle, przypisanie, instrukcja
+wi���ca, instrukcja wyboru.
+
+3) Wyra�enia -- czyli wszystko to, co mo�na do czego� przypisa�, co ma
+jak�� warto��, na przyk�ad: sta�e, odwo�ania do zmiennych i sta�ych
+nazwanych, wywo�anie funkcji, operatory binarne, operatory unarne, etc.
+
+Pole m�wi�ce o rodzaju w�z�a wyst�puje zawsze jako pierwsze i jest zawsze
+tego samego typu -- tak aby u�ywaj�c rzutowania na kt�r�kolwiek z
+kategorii w�z��w wska�nika void* mo�na by�o pozna� w�a�ciw� kategori�.
+
+Kraw�dzie
+---------
+
+Po��czenia pomi�dzy w�z�ami to po prostu wska�niki umieszczone jako pola w
+odpowiednich strukturach danych. Ich znaczenie zale�y cz�ciowo od
+kategorii i rodzaju w�z�a, cho� s� tak�e `uniwersalne', takie jak pola na
+komentarze.
+
+Informacja o po��czeniach w drug� stron� -- to znaczy informacja o przodku
+danego w�z�a -- jest znacznie prostrza do przechowania i zale�y tylko od
+kaztegorii w�z�a.
+
+1) Symbole -- mog� by� potomkami wy��cznie innych symboli. Wobec tego ich
+pole `parent' jest wska�nikiem na symbol.
+
+2) Polecenia -- mog� by� potomkami inncyh polece� (jak w instrukcji
+warunkowej lub blokowej). Jedyny przypadek gdy tak nie jest dotyczy
+instrukcji blokowej (BEGIN...END) i jest traktowany jako przypadek
+szczeg�lny. Je�li pole parent takiej instrukcji jest r�wne NULL, to
+rodzicem takiego w�z�a jest jaki� symbol, zapisany np. w polu symbol.
+
+3) Wyra�enia -- tutaj jest du�y problem. Wyra�enia mog� wyst�pi� jako
+cz�ci sk�adowe wi�kszych wyra�e�, jako parametry polece�, a tak�e w
+definicjach sta�ych nazwanych i typ�w.
+Ze wzgl�du na do�� du�y stopie� komplikacji, jak i raczej niewielkie
+mo�liwo�ci zastosowania, wyra�enia nie b�d� prawdopodobnie zna�y swoich
+przodk�w.
+
+
+Symbole
+-------
+
+SymbolNode
+	kind		Zmienna wyliczeniowa, opisuje dok�adny rodzaj
+			w�z�a.
+			
+	name	 	Nazwa danego symbolu (z zachowaniem pierwszy raz
+			napotkanej wielko�ci liter).
+			
+	namespace	Tablica symboli-dzieci (zar�wno w postaci tablicy
+			hashuj�cej jak i listy dla zachowania kolejno�ci).
+			Ma warto�� NULL dla symboli nie mog�cych mie�
+			dzieci (bezp�odne?).  Symbole na li�cie mog� si�
+			powtarza�. W�wczas pierwsze wyst�pienie oznacza
+			tylko deklaracj�, a nast�pne oznacza definicj�.
+			
+	parent		Wska�nik na bezpo�redniego przodka w drzewie. Ma
+			warto�� NULL dla korzenia.  Wskazuje w kt�rym
+			miejscu symbol zosta� zadeklarowany.
+			
+	body		Wska�nik na w�ze� instrukcji blokowej stanowi�cej
+			cia�o danego programu, procedury lub funkcji.
+			Tak�e rozkaz przy kt�rym znajduje si� dana
+			etykieta. Ma warto�� NULL dla pozosta�ych rodzaj�w
+			symboli.
+
+	type		Wska�nik na symbol, w domy�le opisuj�cy typ danego
+			w�z�a lub jego typ bazowy (dla innych typ�w). Dla
+			symboli nie maj�cych typu ma warto�� NULL.
+
+	used		Lista wska�nik�w do w�z��w w kt�rych u�ywany jest
+			ten symbol. Dla programu jest to lista nazw
+			podanych po nazwie.
+
+Polecenia
+---------
+
+StmtNode
+	kind		Zmienna wyliczeniowa, opisuje dok�adny rodzaj
+			w�z�a.
+			
+	parent		Wska�nik do instrukcji blokowej w kt�rej jest to
+			polecenie zawarte. Dla instrukcji blokowej b�d�cej
+			cia�em programu, funkcji lub procedury -- ma
+			warto�� NULL.
+	
+	label		Je�li polecenie jest zaetykietowane jest to
+			wska�nik do etykiety.  W przeciwnym wypadku NULL.
+
+	list		Dla instrukcji blokowej i p�tli REPEAT -- lista
+			polece� zawartych wewn�trz. Dla wywo�ania
+			procedury lista parametr�w aktualnych. Dla
+			instrukcji wyboru -- lista wariant�w CASE. Dla
+			instrukcji WITH -- lista zmiennych rekordowych.
+			Dla pozosta�ych w�z��w NULL.
+	
+	stmt1		Dla p�tli WHILE, instrukcji WITH i FOR oraz
+			wariant�w CASE jest to wska�nik do zawartego w
+			nich polecenia. Dla instrukcji warunkowej --
+			polecenia zaraz po THEN. Dla pozosta�ych w�z�ow
+			NULL.
+
+	stmt2		Dla instrukcji warunkowej -- polecenie po ELSE.
+			Dla pozosta�ych w�z��w NULL.
+	
+	symbol		Dla instrukcji blokowej -- symbol kt�rej jest ona
+			cia�em. Dla instrukcji przypisania -- zmienna do
+			kt�rej nast�puje przypisanie. Dla instrukcji skoku
+			-- etykieta do kt�rej nalezy wykona� skok. Dla
+			instrukcji FOR -- licznik p�tli.  Dla pozosta�ych
+			w�z��w NULL.
+	
+	expr1		Dla instrukcji przypisania -- wyra�enie kt�re
+			nale�y przypisa�. Dla p�tli REPEAT i WHILE --
+			warunek ko�ca (kontynuacji) p�tli. Dla p�tli FOR
+			-- warto�� pocz�tkowa licznika. Dla instrukcji
+			wyboru i instrukcji warunkowej -- wyra�enie
+			prze��czaj�ce. Dla wariant�w CASE -- wyra�enie
+			przy kt�rym dany wariant ma zastosowanie. Dla
+			pozosta�ych NULL.
+	
+	expr2		Dla p�tli FOR -- warto�� ko�cowa licznika. Dla
+			pozosta�ych warto�ci NULL.
+
+Wyra�enia
+---------
+
+ExprNode
+	kind		Zmienna wyliczeniowa, opisuje dok�adny rodzaj
+			w�z�a.
+
+	list		Dla wywo�ania funkcji -- lista parametr�w
+			formalnych.
+	
+	expr1		Dla operator�w binarnych i unarnych -- warto�� na
+			jakiej dzia�aj�.
+	
+	expr2		Dla operator�w binarnych -- druga warto�� na
+			jakiej dzia�a.
+
+	symbol		Dla wywo�a� zmiennych i funkcji -- dana zmienna
+			lub funkcja. Dla operatora @ -- symbol kt�rego
+			adres zwraca.
+	
+	value		Dla sta�ych -- w�a�ciwa warto�� danej sta�ej.

File docs/pliki.txt

+Spis plik�w wraz z przeznaczeniem
+=================================
+
+
+Makefile
+--------
+
+Plik z instrukcjami dla programu make dotycz�cymi kompilowania ca�ego
+programu.
+
+
+main.c
+------
+
+G��wna procedura programu. Na razie tylko wywo�uje parser dla podanego
+pliku.
+
+
+keywords.c, keywords.h
+----------------------
+
+Statyczna tablica s��w kluczowych, obs�uga wyszukiwania s��w kluczowych.
+
+
+parser.c, parser.h
+------------------
+
+Definicja i procedury tworz�ce i niszcz�ce objekt parsera.
+
+
+pascal.l
+--------
+
+Skaner leksykalny do turbo pascala, napisany w lex'ie (flex'ie).
+Pierwotna wersja skanera, napisana bezpo�rednio w C by�a zbyt
+skomplikowana i trudna do debugowania. Lex automatycznie generuje z tego
+plik �r�d�owy skanera.
+
+
+pascal.y
+--------
+
+Serce ca�ego programu -- definicja gramatyki turbo pascala, wraz z akcjami
+jakie maj� by� podj�te przy stosowaniu poszczeg�lnych produkcji.  Powsta�
+z pliku tp4.y do��czonego jako przyk�ad do pascalowej wersji Yacc'a. Bison
+generuje z tego pliki �r�d�owe parsera `pascal.tab.c' i `pascal.tab.h'.
+
+
+symbols.c, symbols.h
+--------------------
+
+Definicje i procedury do obs�ugi przestrzeni nazw (`namespace'), albo
+inaczej -- tablic symboli.
+
+
+utils.c, utils.h
+----------------
+
+Pomocnicze procedury u�ywane przez `pascal.y' oraz `pascal.l', takie jak
+dodawanie i wyszukiwanie symboli zgodnie z w�a�ciwymi regu�ami, zmienianie
+przestrzenii nazw, etc.
+
+
+node.c. node.h
+--------------
+
+Definicje, konstruktory i destruktory do poszczeg�lnych rodzaj�w
+wierzcho�k�w drzewa parsowania.
+
+
+showtree.c, showtree.h
+----------------------
+
+Procedury do wy�wietlania informacji o poszczeg�lnych rodzajach
+wierzcho�k�w.
+do przestrzeni nazw, wyszukiwanie

File docs/skaner.txt

+Opis skanera leksykalnego dla Turbo Pascala
+===========================================
+
+
+Streszczenie
+------------
+
+Jest to opis skanera leksykalnego zawartego w pliku `pascal.l'.  Skaner
+leksykalny zajmuje si� podzia�em tekstu �r�d�owego na `tokeny' oraz
+rozpoznawaniem ich typ�w.  Ze wzgl�du na charakter gramatyki j�zyka Turbo
+Pascal, ten skaner leksykalny dokonuje tak�e wyszukiwania symboli w
+tablicach -- aby dostarczy� parserowi dodatkowe, niezb�dne mu informacje.
+
+
+Format
+------
+
+Skaner jest napisany w formacie obs�ugiwanym przez program `lex',
+konkretnie przez jego implementacj� o nazwie `flex' (fast lex).  W�a�ciwy
+kod �r�d�owy skanera jest generowany w spos�b automatyczny przez ten
+program i umieszczany w pliku `lex.yy.c'.  Dok�adny opis formatu znajduje
+si� na stronie manuala flex'a, oraz na stronie info.
+
+
+Wyra�enia
+---------
+
+W�a�ciwie tre�ci� tego pliku jest lista wyra�e� regularnych, z
+odpowiadaj�cymi im akcjami.  Wyra�enia regularne opisuj� poszczeg�lne
+elementy j�zyka, takie jak:
+
+- identyfikatory i s�owa kluczowe;
+- sta�e liczbowe ca�kowite;
+- sta�e liczbowe zmiennoprzecinkowe;
+- sta�e liczbowe szesnastkowe;
+- sta�e znakowe;
+- sta�e tekstowe;
+- komentarze blokowe;
+- komentarze w kodzie;
+- operatory wieloznakowe, takie jak `:=', `>=', `..', czy `(.';
+- pojedy�cze symbole;
+
+
+Identyfikatory i s�owa kluczowe
+-------------------------------
+
+Zar�wno identyfikatory, jak i s�owa kluczowe trafiaj� do tej samej
+procedury, w kt�rej s� nast�pnie rozpoznawane.  W pierwszej kolejno�ci
+sprawdzane jest, czy nie jest to s�owo kluczowe -- w tym celu przegl�dana
+jest tablica s��w kluczowych.  Je�li s�owo zostaje znalezione, to zwracany
+jest jego numer.  W przeciwnym wypadku nast�puje wyszukiwanie w tablicy
+symboli -- spos�b wyszukiwania zale�y od stanu parsera.  Mo�liwe s� dwa
+przypadki:
+
+1) Przeszukiwana jest aktualna tablica symboli, je�li symbol nie zosta�
+odnaleziony, przeszukiwana jest nast�pna na stosie. Kiedy zostanie
+osi�gniety koniec stosu a symbol nie zosta� odnaleziony, zwracany jest
+token `ID_NAME' oznaczaj�cy identyfikator bez nadanego jeszcze znaczenia.
+
+2) Je�li zmienna parsera `levelup' jest wyzerowana, to sprawdzana jest
+tylko tablica symboli na wierzcho�ku stosu.  Dzieje si� tak, na przyk�ad,
+przy definicji nowej zmiennej lokalnej o nazwie takiej, jak ju� istniej�ca
+zmienna globalna.  Skaner zwr�ci w�wczas `ID_NAME', czyli nazw� do
+wykorzystania, a nie odleziony symbol zmiennej globalnej.
+
+
+Sta�e
+-----
+
+Sta�e rozpoznawane s� zgodnie z definicj� j�zyka Turbo Poscal, przy czym
+ich warto�� zapami�tywana jest jako tekst -- aby nie traci� dodatkowego
+znaczenia jakie mo�e mie� spos�b zapisu sta�ej dla programisty.  Jest to
+wygodne i dopuszczalne, gdy� warto�ci sta�ych nie s� do niczego w
+programie uzywane -- poza ich zapami�taniem.
+
+
+Komentarze
+----------
+
+Skaner leksykalny rozpoznaje dwa rodzaje komentarzy, kt�re traktuje na
+r�ne sposoby.  S� to:
+
+1) Komentarze blokowe -- czyli komentarze wyst�puj�ce samodzielnie w danej
+linii.  Ich przeznaczeniem s� opisy funkcji, procedur, zastosowanych
+algorytm�w, a tak�e r�nego rodzaju pomocnicze uwagi.  Wykomentowany kod
+�r�d�owy tak�e wpada do tej kategorii.
+
+2) Komentarze w kodzie -- s� to komentarze wyst�puj�ce w tej samej linii
+co kod (na ko�cu linii).  Ich przeznaczeniem jest opisywanie zmiennych,
+kr�tkie komentarze dotycz�ce kodu, kr�tkie uwagi.
+
+Dla parsera komentarze s� ignorowane -- nie dostaje on o nich �adnej
+informacji.  Natomiast w momencie, kiedy tworzony jest nowy w�ze� drzewa
+parsowania, mo�e on otrzyma� jeden lub oba z typ�w komentarzy.
+
+Podobnie jak sta�e, komentarze s� przechowywane w postaci dos�ownego
+tekstu.  Ewentualne reformatowanie komentarzy mo�e nast�pi� w dalszej
+cz�ci programu, cho� istnieje niebezpiecze�stwo zniszczenia takich
+konstrukcji jak tabelki, wyliczenia, itp.  Idealne by�yby komentarze w
+XML-u, tak jak w C# :).
+
+Wieloliterowe operatory
+-----------------------
+
+Gramatyka Turbo Pascala zawiera kilka symboli sk�adaj�cych si� z kilku
+znak�w, a tak�e alternatywne sposobu zapisu nawias�w kwadratowych `[]' i
+klamrowych `{}'.  O ile te ostatnie obs�ugiwane s� w cz�ci dotycz�cej
+komentarzy, o tyle pozosta�e musz� zosta� uwzgl�dnione oddzielnie.

File docs/spec.txt

File contents unchanged.

File docs/squares.txt

+Algorithms for finding largest free squares
+===========================================
+
+
+Abstract
+--------
+
+This article present several algorithms for finding the largest free
+(UN-obstructed) rectangle on two dimensional map.
+The algorithms are quite efficient, but I think you can improve them
+further.
+
+
+1. rectangle with given starting point
+--------------------------------------
+
+This algorithm checks all the rectangles with it's upper-left corner at
+given point, and picks the largest one.
+
+A rectangle can be represented by two pairs of coordinates: it's upper-left
+corner, called `starting point' from now on, and it's lower-right corner,
+called `end point'.  We will need a structure to keep information on
+squares. We will put there the starting coordinates (sx, sy), the end
+coordinates (ex, ey), and the flags used in the algorithm.
+For starts, let's use two flags: BLOCKED_RIGHT and BLOCKED_DOWN.
+
+Let's create a `one-point' rectangle, with starting and end
+coordinates being equal and both flags cleared.
+
+Let's push it on the stack, set the answer temporarily to this rectangle
+and repeat:
+
+- Pop a rectangle from stack.
+- If BLOCKED_RIGHT flag is clear, check the points immediately right from
+  the rectangle. Check the points from top to bottom. 
+	- If there is point that's not free, and it's not the topmost point, create
+	  new rectangle with the same starting point, but with end point being the
+	  last free point. Set it's BLOCKED_DOWN flag and push it on stack.
+	- If there is point that's not free, set the BLOCKED_RIGHT flag.
+	- If all points are free -- expand our rectangle by one right (increase
+	  the x coordinate of it's end point).
+- else if BLOCKED_DOWN flag is clear, check the points immediately down from
+  the rectangle. Check the points from left to right.
+	- If there is point that's not free, and it's not the leftmost point, create
+	  new rectangle with the same starting point, but with end point being the
+	  last free point. Set it's BLOCKED_RIGHT flag and push it on stack.
+	- If there is point that's not free, set the BLOCKED_DOWN flag.
+	- If all points are free -- expand our rectangle by one down (increase
+	  the y coordinate of it's end point).
+- else if both flags are set, count the rectangle's size, compare it with size of
+  rectangle in temporary answer.  If it's larger, replace the answer with
+  our rectangle.
+- If at least one flag is clear, push the rectangle back on stack.
+
+You can add a loop to get rid of unnecessary stack pushes and pops when at
+least one flag is clear.
+You finish when the stack is empty. The temporary answer contains the
+largest free rectangle with it's upper-left corner in given point.
+
+
+
+2. rectangle containing specified point
+---------------------------------------
+
+You can slightly modify this algorithm to search for the largest rectangle
+containing given point.
+
+First, we will need two more flags, BLOCKED_UP and BLOCKED_LEFT, together
+with corresponding parts of code:
+
+Let's create a `one-point' rectangle, with starting and end
+coordinates being equal and all the flags cleared.
+
+Let's push it on the stack, set the answer temporarily to this rectangle
+and repeat:
+
+- Pop a rectangle from stack.
+- If BLOCKED_RIGHT flag is clear, check the points immediately right from
+  the rectangle. Check the points from top to bottom. 
+	- If there is point that's not free, and it's not the topmost point, create
+	  new rectangle with the same starting point, but with end point being the
+	  last free point. Set it's BLOCKED_DOWN flag and push it on stack.
+	- If there is point that's not free, set the BLOCKED_RIGHT flag.
+	- If all points are free -- expand our rectangle by one right (increase
+	  the x coordinate of it's end point).
+- else if BLOCKED_DOWN flag is clear, check the points immediately down from
+  the rectangle. Check the points from left to right.
+	- If there is point that's not free, and it's not the leftmost point, create
+	  new rectangle with the same starting point, but with end point being the
+	  last free point. Set it's BLOCKED_RIGHT flag and push it on stack.
+	- If there is point that's not free, set the BLOCKED_DOWN flag.
+	- If all points are free -- expand our rectangle by one down (increase
+	  the y coordinate of it's end point).
+- else if BLOCKED_LEFT flag is clear, check the points immediately left from
+  the rectangle. Check the points from top to bottom.
+	- If there is point that's not free, and it's not the topmost point, create
+	  new rectangle with the starting point being the one above the
+	  obstructed point, at height of our given point, and with end
+	  above our rectangle's end point, at height one above the
+	  obstructed point. Set it's BLOCKED_DOWN flag and push it on stack.
+	- If there is point that's not free, set the BLOCKED_LEFT flag.
+	- If all points are free -- expand our rectangle by one left (decrease
+	  the x coordinate of it's start point).
+- else if BLOCKED_UP flag is clear, check the points immediately up from
+  the rectangle. Check the points in two passes, every time beginning
+  above our given point and moving left and right.
+	- If there is point that's not free, and it's not the first point
+	  (the one above our given point), create new rectangle.
+	  It's left boundary should be immediately to the right of first
+	  not free point in right-to-left pass, and it's left boundary
+	  should be immediately to the left of first not free point in
+	  the left-to-right pass. It's top boundary should be one above
+	  our rectangle's boundary, and it's bottom boundary is the same
+	  as our rectangle's. Set it's BLOCKED_RIGHT if there was not-free
+	  point in left-to-right pass, and the BLOCKED_LEFT if there was a
+	  not free point in right-to-left pass. Push it on stack.
+	- If there is point that's not free, set the BLOCKED_UP flag.
+	- If all points are free -- expand our rectangle by one up (decrease
+	  the y coordinate of it's start point).
+- else if both flags are set, count the rectangle's size, compare it with size of
+  rectangle in temporary answer.  If it's larger, replace the answer with
+  our rectangle.
+- If at least one flag is clear, push the rectangle back on stack.
+
+The BLOCKED_UP part is most complicated, because on this stage our
+rectangles are on both sides of our given point.
+
+The BLOCKED_LEFT and BLOCKED_UP parts may examine rectangles that are
+contained in other, separately checked ones.  But I think avoiding it is a
+bit tedious.
+
+
+3. largest rectangle on whole map
+---------------------------------
+
+This is a bit complicated. You can use the first algorithm to check all
+the starting points. But it's a bit ineffective -- you check many points
+multiple times.  What we need is a way of marking the points that the
+largest rectangle cannot start at.
+
+How to recognize those points?
+Every time a rectangle hits an obstacle, you need to find the obstacle
+ends. That is, in your check, when you find a not free point, go further
+and find the first free point. If there isn't one, assume it's the one
+after the last point you check. Remember this point.
+When the rectangle hits an obstacle in the other direction, find the
+second point.
+
+Now you can mark all the points in rectangle, which upper-left corner is
+the starting point of our rectangles and it's lower-left and upper-right
+corners are the two points you found. Any rectangle starting in these
+points is smaller than the one you just considered.
+
<