Initial checkin of picoc. Not working yet.

git-svn-id: http://picoc.googlecode.com/svn/trunk@2 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2008-10-13 00:53:28 +00:00
parent bc1b85ab0b
commit 7bfc2c0be5
8 changed files with 583 additions and 0 deletions

22
Makefile Normal file
View file

@ -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

5
hello.c Normal file
View file

@ -0,0 +1,5 @@
int main()
{
printf("Hello world\n");
}

109
lex.c Normal file
View file

@ -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;
}

36
parse.c Normal file
View file

@ -0,0 +1,36 @@
#include <stdio.h>
#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)
{
}

90
picoc.c Normal file
View file

@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#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 <program.c> <args>...\n");
ParseInit();
StrFromC(&FileName, argv[1]);
ScanFile(&FileName);
StrFromC(&StartFunc, "main");
ParseCallFunction(&StartFunc, argc-1, &argv[1]);
return 0;
}

144
picoc.h Normal file
View file

@ -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 */

55
str.c Normal file
View file

@ -0,0 +1,55 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#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;
}
}

122
table.c Normal file
View file

@ -0,0 +1,122 @@
#include <string.h>
#include "picoc.h"
#ifdef USE_MALLOC
#include <stdlib.h>
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