From 7bfc2c0be5f4869c738cb9eec67e25f6ed055973 Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Mon, 13 Oct 2008 00:53:28 +0000 Subject: [PATCH] Initial checkin of picoc. Not working yet. git-svn-id: http://picoc.googlecode.com/svn/trunk@2 21eae674-98b7-11dd-bd71-f92a316d2d60 --- Makefile | 22 +++++++++ hello.c | 5 ++ lex.c | 109 +++++++++++++++++++++++++++++++++++++++++ parse.c | 36 ++++++++++++++ picoc.c | 90 ++++++++++++++++++++++++++++++++++ picoc.h | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ str.c | 55 +++++++++++++++++++++ table.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 583 insertions(+) create mode 100644 Makefile create mode 100644 hello.c create mode 100644 lex.c create mode 100644 parse.c create mode 100644 picoc.c create mode 100644 picoc.h create mode 100644 str.c create mode 100644 table.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c358fc2 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +CC=gcc +CFLAGS=-Wall -g + +TARGET = picoc +SRCS = picoc.c table.c str.c parse.c lex.c +OBJS := $(SRCS:%.c=%.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) + +clean: + rm -f $(TARGET) $(OBJS) *~ + +count: + wc $(SRCS) picoc.h + +depend: + $(CC) -MM $(SRCS) >.depend + +-include .depend diff --git a/hello.c b/hello.c new file mode 100644 index 0000000..0cf55b8 --- /dev/null +++ b/hello.c @@ -0,0 +1,5 @@ +int main() +{ + printf("Hello world\n"); +} + diff --git a/lex.c b/lex.c new file mode 100644 index 0000000..fd724c3 --- /dev/null +++ b/lex.c @@ -0,0 +1,109 @@ +#include "picoc.h" + +#define LEXINC Lexer->Pos++ +#define NEXTIS(c,x,y) { if (NextChar == (c)) { LEXINC; return (x); } else return (y); } +#define NEXTIS3(c,x,d,y,z) { if (NextChar == (c)) { LEXINC; return (x); } else NEXTIS(d,y,z) } +#define NEXTIS4(c,x,d,y,e,z,a) { if (NextChar == (c)) { LEXINC; return (x); } else NEXTIS3(d,y,e,z,a) } + +struct ReservedWord +{ + const char *Word; + enum LexToken Token; +}; + +static char *ReservedWords[] = +{ + { "char", TokenCharType }, + { "do", TokenDo }, + { "else", TokenElse }, + { "for", TokenFor }, + { "if", TokenIf }, + { "int", TokenIntType }, + { "while", TokenWhile }, + { "void", TokenVoidType } +}; + +void LexInit(struct LexState *Lexer, const Str *Source, int Line) +{ + Lexer->Pos = Source->Str; + Lexer->End = Source->Str + Source->Len; + Lexer->Line = Line; +} + + +enum LexToken LexCheckReservedWord(const Str *Word) +{ + int Count; + + for (Count = 0; Count < sizeof(ReservedWords) / sizeof(struct ReservedWord); Count++) + { + if (StrEqualC(Word, ReservedWord[Count].Word)) + return ReservedWord[Count].Token; + } + + return TokenNone; +} + + +enum LexToken LexGetNumber(struct LexState *Lexer) +{ + XXX +} + + +enum LexToken LexGetWord(struct LexState *Lexer) +{ + XXX +} + + +enum LexToken LexGetToken(struct LexState *Lexer) +{ + char ThisChar; + char NextChar; + + while (Lexer->Pos != Lexer->End && isspace(*Lexer->Pos)) + Lexer->Pos++; + + if (Lexer->Pos == Lexer->End) + return TokenEOF; + + ThisChar = *Lexer->Pos; + if (isCidstart(ThisChar)) + return LexGetWord(Lexer); + + if (isdigit(ThisChar)) + return LexGetNumber(Lexer); + + NextChar = (Lexer->Pos+1 != Lexer->End) ? *(Lexer->Pos+1) : 0; + LEXINC; + switch (ThisChar) + { + case '"': return LexGetStringConstant(Lexer); + case '\'': return LexGetCharacterConstant(Lexer); + case '(': return TokenOpenBracket; + case ')': return TokenCloseBracket; + case '=': NEXTIS('=', TokenEquality, TokenAssignment); + case '+': NEXTIS3('=', TokenAddAssign, '+', TokenIncrement, TokenPlus); + case '-': NEXTIS4('=', TokenSubtractAssign, '>', TokenArrow, '-', TokenDecrement, TokenMinus); + case '*': return TokenAsterisk; + case '/': return TokenSlash; + case '<': NEXTIS('=', TokenLessEqual, TokenLess); + case '>': NEXTIS('=', TokenGreaterEqual, TokenGreater); + case ';': return TokenSemiColon; + case '&': NEXTIS('&', TokenLogicalAnd, TokenAmpersand); + case '|': NEXTIS('|', TokenLogicalOr, TokenArithmeticOr); + case '{': return TokenLeftBrace; + case '}': return TokenRightBrace; + case '[': return TokenLeftAngleBracket; + case ']': return TokenRightAngleBracket; + case '^': return TokenArithmeticExor; + case '~': return TokenUnaryExor; + case ',': return TokenComma; + case '.': return TokenDot; + } + + ProgramError(Lexer->FileName, Lexer->Line, "illegal character '%c'", ThisChar); + return TokenEOF; +} + diff --git a/parse.c b/parse.c new file mode 100644 index 0000000..ef40497 --- /dev/null +++ b/parse.c @@ -0,0 +1,36 @@ +#include + +#include "picoc.h" + +/* the table of global definitions */ +struct Table GlobalTable; +struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE]; + + +void ParseInit() +{ + TableInit(&GlobalTable, &GlobalHashTable[0], "global", GLOBAL_TABLE_SIZE); +} + + +/* quick scan a source file for definitions */ +void ParseScan(const Str *FileName, const Str *Source) +{ + enum LexToken Token; + + LexInit(Source); + + while ( (Token = LexGetToken()) != TokenEOF) + { + /* do parsey things here */ + printf("token %d\n", (int)Token); + } +} + + +void ParseCallFunction(const Str *FuncIdent, int argc, char **argv) +{ +} + + + diff --git a/picoc.c b/picoc.c new file mode 100644 index 0000000..61eedde --- /dev/null +++ b/picoc.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include + +#include "picoc.h" + +/* all platform-dependent code is in this file */ + +void Fail(const char *Message, ...) +{ + va_list Args; + + va_start(Args, Message); + vprintf(Message, Args); + exit(1); +} + +void ProgramError(const Str *FileName, int Line, const char *Message, ...) +{ + va_list Args; + + StrPrintf("%S:%d: ", FileName, Line) + va_start(Args, Message); + vprintf(Message, Args); + printf("\n"); + exit(1); +} + +/* read a file into memory. this is the only function using malloc(). + * do it differently for embedded devices without malloc */ +char *ReadFile(const Str *FileName) +{ + struct stat FileInfo; + char *Text; + FILE *InFile; + char CFileName[PATH_MAX]; + + StrToC(CFileName, PATH_MAX, FileName); + + if (stat(CFileName, &FileInfo)) + Fail("can't read file %s\n", CFileName); + + Text = malloc(FileInfo.st_size); + + InFile = fopen(CFileName, "r"); + if (InFile == NULL) + Fail("can't read file %s\n", CFileName); + + if (fread(Text, 1, FileInfo.st_size, InFile) != FileInfo.st_size) + Fail("can't read file %s\n", CFileName); + + fclose(InFile); + + return Text; +} + +/* read and scan a file for definitions */ +void ScanFile(const Str *FileName) +{ + char *Source; + Str SourceStr; + + Source = ReadFile(FileName); + StrFromC(&SourceStr, Source); + ParseScan(FileName, &SourceStr); +} + +int main(int argc, char **argv) +{ + Str FileName; + Str StartFunc; + + printf("picoc\n"); + + if (argc < 2) + Fail("Format: picoc ...\n"); + + ParseInit(); + + StrFromC(&FileName, argv[1]); + ScanFile(&FileName); + + StrFromC(&StartFunc, "main"); + ParseCallFunction(&StartFunc, argc-1, &argv[1]); + + return 0; +} diff --git a/picoc.h b/picoc.h new file mode 100644 index 0000000..a2c6011 --- /dev/null +++ b/picoc.h @@ -0,0 +1,144 @@ +#ifndef PICOC_H +#define PICOC_H + +/* configurable options */ +#define USE_MALLOC +#define GLOBAL_TABLE_SIZE 199 + +/* handy definitions */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef min +#define min(x,y) (((x)<(y))?(x):(y)) +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +/* lexical tokens */ +enum LexToken +{ + TokenNone, + TokenEOF, + TokenIdentifier, + TokenIntegerConstant, + TokenStringConstant, + TokenCharacterConstant, + TokenType, + TokenOpenBracket, + TokenCloseBracket, + TokenAssign, + TokenPlus, + TokenMinus, + TokenAsterisk, + TokenSlash, + TokenEquality, + TokenLessThan, + TokenGreaterThan, + TokenLessEqual, + TokenGreaterEqual, + TokenSemicolon, + TokenArrow, + TokenAmpersand, + TokenLeftBrace, + TokenRightBrace, + TokenLeftAngleBracket, + TokenRightAngleBracket, + TokenLogicalAnd, + TokenLogicalOr, + TokenArithmeticOr, + TokenArithmeticExor, + TokenUnaryExor, + TokenComma, + TokenDot, + TokenAddAssign, + TokenSubtractAssign, + TokenIncrement, + TokenDecrement, + TokenIntType, + TokenCharType, + TokenVoidType, + TokenDo, + TokenElse, + TokenFor, + TokenIf, + TokenWhile +}; + +/* string type so we can use source file strings */ +typedef struct _Str +{ + int Len; + const char *Str; +} Str; + + +/* hash table data structure */ +struct TableEntry +{ + Str Key; + void *Value; +}; + +struct Table +{ + const char *Name; + short Size; + struct TableEntry *HashTable; +}; + + +/* function definition - really just where it is in the source file */ +struct FuncDef +{ + Str Source; + Str FileName; + int StartLine; +}; + + +/* lexer state - so we can lex nested files */ +struct LexState +{ + int Line; + const char *Pos; + const char *End; +}; + + +/* str.c */ +void StrToC(char *Dest, int DestSize, const Str *Source); +void StrFromC(Str *Dest, const char *Source); +int StrEqual(const Str *Str1, const Str *Str2); +int StrEqualC(const Str *Str1, const char *Str2); +void StrPrintf(const str *Format, ...); + +/* picoc.c */ +void Fail(const char *Message, ...); +void ProgramError(const Str *FileName, int Line, const char *Message, ...); +void ScanFile(const Str *FileName); + +/* table.c */ +void TableInit(struct Table *Tbl, struct TableEntry *HashTable, const char *Name, int Size); +void TableSet(struct Table *Tbl, const Str *Key, void *Value); +void *TableLookup(struct Table *Tbl, const Str *Key); + +/* lex.c */ +void LexInit(const Str *Source); +enum LexToken LexGetToken(void); + +/* parse.c */ +void ParseInit(void); +void ParseScan(const Str *FileName, const Str *Source); +void ParseCallFunction(const Str *FuncIdent, int argc, char **argv); + +#endif /* PICOC_H */ + diff --git a/str.c b/str.c new file mode 100644 index 0000000..e108fd2 --- /dev/null +++ b/str.c @@ -0,0 +1,55 @@ +#include +#include +#include + +#include "picoc.h" + + +void StrToC(char *Dest, int DestSize, const Str *Source) +{ + int CopyLen = min(DestSize-1, Source->Len); + memcpy(Dest, Source->Str, CopyLen); + Dest[CopyLen] = '\0'; +} + + +void StrFromC(Str *Dest, const char *Source) +{ + Dest->Str = Source; + Dest->Len = strlen(Source); +} + + +int StrEqual(const Str *Str1, const Str *Str2) +{ + if (Str1->Len != Str2->Len) + return FALSE; + + return memcmp(Str1->Str, Str2->Str, Str1->Len) == 0; +} + + +int StrEqualC(const Str *Str1, const char *Str2) +{ + return strncmp(Str1->Str, Str2, Str1->Len) == 0 && Str2[Str1->Len] == '\0'; +} + + +void StrPrintf(const str *Format, ...) +{ + char FormatBuf[MAX_FORMAT]; + const char *FPos; + char *BPos; + va_list Args; + + va_start(Args, Format); + for (FPos = Format, BPos = &FormatBuf[0]; *FPos != '\0'; FPos++, BPos++) + { + if (*FPos == '%') + { + XXX + } + *BPos = *FPos; + } +} + diff --git a/table.c b/table.c new file mode 100644 index 0000000..7879450 --- /dev/null +++ b/table.c @@ -0,0 +1,122 @@ +#include + +#include "picoc.h" + + +#ifdef USE_MALLOC +#include + + +static unsigned int TableHash(const Str *Key) +{ + unsigned int Hash; + int Count; + int Offset; + const char *KeyPos; + + Hash = Key->Len; + KeyPos = Key->Str; + Offset = 8; + for (Count = 0; Count < Key->Len; Count++, Offset+=7) + { + if (Offset > sizeof(unsigned int) * 8 - 7) + Offset -= (sizeof(unsigned int)-1) * 8; + + Hash ^= *KeyPos++ << Offset; + } + + return Hash; +} + + +void TableInit(struct Table *Tbl, struct TableEntry *HashTable, const char *Name, int Size) +{ + Tbl->Name = Name; + Tbl->Size = Size; + Tbl->HashTable = HashTable; + memset(HashTable, '\0', sizeof(struct TableEntry) * Size); +} + + +static int TableCheckEntry(struct Table *Tbl, const Str *Key, int HashPos) +{ + struct TableEntry *Entry = &Tbl->HashTable[HashPos]; + + if (Entry->Key.Len == 0) + return -1; /* empty */ + + else if (StrEqual(&Entry->Key, Key)) + return HashPos; /* found */ + + else + return -2; /* wrong key */ +} + + +static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt) +{ + int HashValue; + int HashPos; + int Result; + + HashValue = TableHash(Key) % Tbl->Size; + + for (HashPos = HashValue; HashPos < Tbl->Size; HashPos++) + { + *AddAt = HashPos; + if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2) + return Result; + } + + for (HashPos = 0; HashPos < HashValue; HashPos++) + { + *AddAt = HashPos; + if ( (Result = TableCheckEntry(Tbl, Key, HashPos)) != -2) + return Result; + } + + /* not found and table is full */ + *AddAt = -1; + return -1; +} + + +void TableSet(struct Table *Tbl, const Str *Key, void *Value) +{ + int HashPos; + int AddAt; + + HashPos = TableSearch(Tbl, Key, &AddAt); + + if (HashPos != -1) + Tbl->HashTable[HashPos].Value = Value; /* found - update value */ + else + { + if (AddAt == -1) + Fail("table '%s' is full\n", Tbl->Name); + + else + { /* add it to the table */ + struct TableEntry *Entry = &Tbl->HashTable[AddAt]; + Entry->Key = *Key; + Entry->Value = Value; + } + } +} + + +void *TableLookup(struct Table *Tbl, const Str *Key) +{ + int HashPos; + int AddAt; + + HashPos = TableSearch(Tbl, Key, &AddAt); + + if (HashPos == -1) + return NULL; + else + return Tbl->HashTable[HashPos].Value; +} + +#endif +