diff --git a/lex.c b/lex.c index 5059887..0192c83 100644 --- a/lex.c +++ b/lex.c @@ -110,7 +110,7 @@ enum LexToken LexGetCharacterConstant(struct LexState *Lexer) { Lexer->Value.Integer = Lexer->Pos[1]; if (Lexer->Pos[2] != '\'') - ProgramError(Lexer->FileName, Lexer->Line, "illegal character '%c'", Lexer->Pos[2]); + ProgramFail(Lexer, "illegal character '%c'", Lexer->Pos[2]); Lexer->Pos += 3; return TokenCharacterConstant; @@ -168,14 +168,14 @@ enum LexToken LexGetToken(struct LexState *Lexer) case '.': return TokenDot; } - ProgramError(Lexer->FileName, Lexer->Line, "illegal character '%c'", ThisChar); + ProgramFail(Lexer, "illegal character '%c'", ThisChar); return TokenEOF; } /* look at the next token without changing the lexer state */ enum LexToken LexPeekToken(struct LexState *Lexer) { - struct LexToken LocalState = *Lexer; + struct LexState LocalState = *Lexer; return LexGetToken(&LocalState); } diff --git a/parse.c b/parse.c index 9618432..b96bb4b 100644 --- a/parse.c +++ b/parse.c @@ -1,4 +1,5 @@ #include +#include #include "picoc.h" @@ -7,12 +8,47 @@ struct Table GlobalTable; struct TableEntry GlobalHashTable[GLOBAL_TABLE_SIZE]; +/* local prototypes */ +int ParseExpression(struct LexState *Lexer, struct Value *Result); +void ParseIntExpression(struct LexState *Lexer, struct Value *Result); + +/* initialise the parser */ void ParseInit() { TableInit(&GlobalTable, &GlobalHashTable[0], "global", GLOBAL_TABLE_SIZE); } +/* define a variable */ +void VariableDefine(struct LexState *Lexer, const Str *Ident, enum ValueType Typ) +{ + struct Value NewValue; + + memset(&NewValue, '\0', sizeof(NewValue)); + NewValue.Typ = Typ; + if (!TableSet(&GlobalTable, Ident, &NewValue, FALSE)) + ProgramFail(Lexer, "'%S' is already defined", Ident); +} + +/* set the value of a variable */ +void VariableSet(struct LexState *Lexer, Str *Ident, struct Value *Val) +{ + if (!TableSet(&GlobalTable, Ident, Val, TRUE)) + ProgramFail(Lexer, "'%S' is undefined", Ident); +} + +/* get the value of a variable. must be defined */ +void VariableGet(struct LexState *Lexer, Str *Ident, struct Value *Val) +{ + struct Value *ValPos; + + if (!TableGet(&GlobalTable, Ident, &ValPos)) + ProgramFail(Lexer, "'%S' is undefined", Ident); + + *Val = *ValPos; +} + +/* parse a single value */ int ParseValue(struct LexState *Lexer, struct Value *Result) { struct LexState PreState = *Lexer; @@ -28,14 +64,14 @@ int ParseValue(struct LexState *Lexer, struct Value *Result) break; case TokenMinus: case TokenUnaryExor: case TokenUnaryNot: - if (!ParseExpression(Lexer, Result)) - ProgramFail(Lexer, "invalid expression"); - + ParseIntExpression(Lexer, Result); + switch(Token) { - case TokenMinus: Result = -Result; break; - case TokenUnaryExor: Result = ~Result; break; - case TokenUnaryNot: Result = !Result; break; + case TokenMinus: Result->Val.Integer = -(Result->Val.Integer); break; + case TokenUnaryExor: Result->Val.Integer = ~(Result->Val.Integer); break; + case TokenUnaryNot: Result->Val.Integer = !(Result->Val.Integer); break; + default: break; } break; @@ -52,7 +88,7 @@ int ParseValue(struct LexState *Lexer, struct Value *Result) ProgramFail(Lexer, "not implemented"); case TokenIdentifier: - ReadVariable(XXX); + VariableGet(Lexer, &Lexer->Value.String, Result); break; default: @@ -63,6 +99,7 @@ int ParseValue(struct LexState *Lexer, struct Value *Result) return TRUE; } +/* parse an expression. operator precedence is not supported */ int ParseExpression(struct LexState *Lexer, struct Value *Result) { struct Value CurrentValue; @@ -112,16 +149,34 @@ int ParseExpression(struct LexState *Lexer, struct Value *Result) case TokenArithmeticOr: TotalValue.Val.Integer = TotalValue.Val.Integer | CurrentValue.Val.Integer; break; case TokenArithmeticExor: TotalValue.Val.Integer = TotalValue.Val.Integer ^ CurrentValue.Val.Integer; break; case TokenDot: ProgramFail(Lexer, "operator not supported"); break; + default: break; } } return TRUE; } +/* parse an expression. operator precedence is not supported */ +void ParseIntExpression(struct LexState *Lexer, struct Value *Result) +{ + if (!ParseExpression(Lexer, Result)) + ProgramFail(Lexer, "expression expected"); + + if (Result->Typ != TypeInt) + ProgramFail(Lexer, "integer value expected"); +} +/* parse a statement which starts with an identifier - either an function or an assignment */ +int ParseIdentStatement(struct LexState *Lexer, int RunIt) +{ + /* XXX */ + return FALSE; +} + +/* parse a statement */ int ParseStatement(struct LexState *Lexer, int RunIt) { - int Conditional; + struct Value Conditional; struct LexState PreState = *Lexer; enum LexToken Token = LexGetToken(Lexer); @@ -140,16 +195,15 @@ int ParseStatement(struct LexState *Lexer, int RunIt) break; case TokenIf: - if (!ParseIntExpression(Lexer, &Conditional)) - ProgramFail(Lexer, "expression expected"); + ParseIntExpression(Lexer, &Conditional); - if (!ParseStatement(Lexer, RunIt && Conditional)) + if (!ParseStatement(Lexer, RunIt && Conditional.Val.Integer)) ProgramFail(Lexer, "statement expected"); if (LexPeekToken(Lexer) == TokenElse) { LexGetToken(Lexer); - if (!ParseStatement(Lexer, RunIt && !Conditional)) + if (!ParseStatement(Lexer, RunIt && !Conditional.Val.Integer)) ProgramFail(Lexer, "statement expected"); } break; @@ -160,13 +214,12 @@ int ParseStatement(struct LexState *Lexer, int RunIt) do { *Lexer = PreConditional; - if (!ParseIntExpression(Lexer, &Conditional)) - ProgramFail(Lexer, "expression expected"); + ParseIntExpression(Lexer, &Conditional); - if (!ParseStatement(Lexer, RunIt && Conditional)) + if (!ParseStatement(Lexer, RunIt && Conditional.Val.Integer)) ProgramFail(Lexer, "statement expected"); - } while (Conditional && RunIt); + } while (Conditional.Val.Integer && RunIt); } break; @@ -179,10 +232,9 @@ int ParseStatement(struct LexState *Lexer, int RunIt) if (!ParseStatement(Lexer, RunIt)) ProgramFail(Lexer, "statement expected"); - if (!ParseIntExpression(Lexer, &Conditional)) - ProgramFail(Lexer, "expression expected"); + ParseIntExpression(Lexer, &Conditional); - } while (Conditional && RunIt); + } while (Conditional.Val.Integer && RunIt); } break; @@ -200,8 +252,7 @@ int ParseStatement(struct LexState *Lexer, int RunIt) ProgramFail(Lexer, "statement expected"); PreConditional = *Lexer; - if (!ParseIntExpression(Lexer, &Conditional)) - ProgramFail(Lexer, "expression expected"); + ParseIntExpression(Lexer, &Conditional); if (LexGetToken(Lexer) != TokenSemicolon) ProgramFail(Lexer, "';' expected"); @@ -213,12 +264,12 @@ int ParseStatement(struct LexState *Lexer, int RunIt) ProgramFail(Lexer, "')' expected"); PreStatement = *Lexer; - if (!ParseStatement(Lexer, Conditional && RunIt)) + if (!ParseStatement(Lexer, Conditional.Val.Integer && RunIt)) ProgramFail(Lexer, "statement expected"); After = *Lexer; - while (Conditional && RunIt) + while (Conditional.Val.Integer && RunIt) { *Lexer = PreIncrement; ParseStatement(Lexer, TRUE); @@ -226,7 +277,7 @@ int ParseStatement(struct LexState *Lexer, int RunIt) *Lexer = PreConditional; ParseIntExpression(Lexer, &Conditional); - if (Conditional) + if (Conditional.Val.Integer) { *Lexer = PreStatement; ParseStatement(Lexer, TRUE); @@ -245,7 +296,7 @@ int ParseStatement(struct LexState *Lexer, int RunIt) if (LexGetToken(Lexer) != TokenIdentifier) ProgramFail(Lexer, "identifier expected"); - DeclareVariable(Lexer, Lexer->Value.String); + VariableDefine(Lexer, &Lexer->Value.String, (Token == TokenVoidType) ? TypeVoid : TypeInt); break; default: @@ -259,12 +310,11 @@ int ParseStatement(struct LexState *Lexer, int RunIt) /* parse and run some code */ void ParseRun(const Str *FileName, const Str *Source, int LineNo) { - enum LexToken Token; struct LexState Lexer; LexInit(&Lexer, Source, FileName, 1); - while (ParseStatement(Lexer, TRUE)) + while (ParseStatement(&Lexer, TRUE)) {} } diff --git a/picoc.c b/picoc.c index 0919bb7..99763d6 100644 --- a/picoc.c +++ b/picoc.c @@ -18,11 +18,11 @@ void Fail(const char *Message, ...) exit(1); } -void ProgramError(const Str *FileName, int Line, const char *Message, ...) +void ProgramFail(struct LexState *Lexer, const char *Message, ...) { va_list Args; - StrPrintf("%S:%d: ", FileName, Line); + StrPrintf("%S:%d: ", Lexer->FileName, Lexer->Line); va_start(Args, Message); vStrPrintf(Message, Args); StrPrintf("\n"); diff --git a/picoc.h b/picoc.h index 5a4ec8f..a83a693 100644 --- a/picoc.h +++ b/picoc.h @@ -74,7 +74,12 @@ enum LexToken TokenElse, TokenFor, TokenIf, - TokenWhile + TokenWhile, + TokenBreak, + TokenSwitch, + TokenCase, + TokenDefault, + TokenReturn }; /* string type so we can use source file strings */ @@ -84,22 +89,6 @@ typedef struct _Str 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 { @@ -108,8 +97,10 @@ struct FuncDef int StartLine; }; +/* values */ enum ValueType { + TypeVoid, TypeInt, TypeString }; @@ -126,6 +117,20 @@ struct Value union AnyValue Val; }; +/* hash table data structure */ +struct TableEntry +{ + Str Key; + struct Value Val; +}; + +struct Table +{ + const char *Name; + short Size; + struct TableEntry *HashTable; +}; + /* lexer state - so we can lex nested files */ struct LexState { @@ -153,8 +158,8 @@ 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); +int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val, int Exists); +int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val); /* lex.c */ void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line); diff --git a/table.c b/table.c index 7879450..b5da12e 100644 --- a/table.c +++ b/table.c @@ -2,10 +2,6 @@ #include "picoc.h" - -#ifdef USE_MALLOC -#include - static unsigned int TableHash(const Str *Key) { @@ -81,15 +77,18 @@ static int TableSearch(struct Table *Tbl, const Str *Key, int *AddAt) } -void TableSet(struct Table *Tbl, const Str *Key, void *Value) +int TableSet(struct Table *Tbl, const Str *Key, struct Value *Val, int Exists) { int HashPos; int AddAt; HashPos = TableSearch(Tbl, Key, &AddAt); + if ( (HashPos != -1) != Exists) + return FALSE; + if (HashPos != -1) - Tbl->HashTable[HashPos].Value = Value; /* found - update value */ + Tbl->HashTable[HashPos].Val = *Val; /* found - update value */ else { if (AddAt == -1) @@ -99,13 +98,15 @@ void TableSet(struct Table *Tbl, const Str *Key, void *Value) { /* add it to the table */ struct TableEntry *Entry = &Tbl->HashTable[AddAt]; Entry->Key = *Key; - Entry->Value = Value; + Entry->Val = *Val; } } + + return TRUE; } -void *TableLookup(struct Table *Tbl, const Str *Key) +int TableGet(struct Table *Tbl, const Str *Key, struct Value **Val) { int HashPos; int AddAt; @@ -113,10 +114,9 @@ void *TableLookup(struct Table *Tbl, const Str *Key) HashPos = TableSearch(Tbl, Key, &AddAt); if (HashPos == -1) - return NULL; - else - return Tbl->HashTable[HashPos].Value; + return FALSE; + + *Val = &Tbl->HashTable[HashPos].Val; + return TRUE; } -#endif -