Now compiles
git-svn-id: http://picoc.googlecode.com/svn/trunk@10 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
8cfd9c6013
commit
a41ac67b50
6
lex.c
6
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);
|
||||
}
|
||||
|
||||
|
|
102
parse.c
102
parse.c
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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))
|
||||
{}
|
||||
}
|
||||
|
||||
|
|
4
picoc.c
4
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");
|
||||
|
|
43
picoc.h
43
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);
|
||||
|
|
28
table.c
28
table.c
|
@ -3,10 +3,6 @@
|
|||
#include "picoc.h"
|
||||
|
||||
|
||||
#ifdef USE_MALLOC
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static unsigned int TableHash(const Str *Key)
|
||||
{
|
||||
unsigned int Hash;
|
||||
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue