Wrote much of the parser
git-svn-id: http://picoc.googlecode.com/svn/trunk@9 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
50c7494508
commit
8cfd9c6013
8
lex.c
8
lex.c
|
@ -161,6 +161,7 @@ enum LexToken LexGetToken(struct LexState *Lexer)
|
|||
case '}': return TokenRightBrace;
|
||||
case '[': return TokenLeftAngleBracket;
|
||||
case ']': return TokenRightAngleBracket;
|
||||
case '!': return TokenUnaryNot;
|
||||
case '^': return TokenArithmeticExor;
|
||||
case '~': return TokenUnaryExor;
|
||||
case ',': return TokenComma;
|
||||
|
@ -171,3 +172,10 @@ enum LexToken LexGetToken(struct LexState *Lexer)
|
|||
return TokenEOF;
|
||||
}
|
||||
|
||||
/* look at the next token without changing the lexer state */
|
||||
enum LexToken LexPeekToken(struct LexState *Lexer)
|
||||
{
|
||||
struct LexToken LocalState = *Lexer;
|
||||
return LexGetToken(&LocalState);
|
||||
}
|
||||
|
||||
|
|
269
parse.c
269
parse.c
|
@ -13,36 +13,259 @@ void ParseInit()
|
|||
TableInit(&GlobalTable, &GlobalHashTable[0], "global", GLOBAL_TABLE_SIZE);
|
||||
}
|
||||
|
||||
int ParseValue(struct LexState *Lexer, struct Value *Result)
|
||||
{
|
||||
struct LexState PreState = *Lexer;
|
||||
enum LexToken Token = LexGetToken(Lexer);
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenIntegerConstant: case TokenCharacterConstant: case TokenStringConstant:
|
||||
Result->Typ = TypeInt;
|
||||
Result->Val = Lexer->Value;
|
||||
if (Token == TokenStringConstant)
|
||||
Result->Typ = TypeString;
|
||||
break;
|
||||
|
||||
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
||||
if (!ParseExpression(Lexer, Result))
|
||||
ProgramFail(Lexer, "invalid expression");
|
||||
|
||||
switch(Token)
|
||||
{
|
||||
case TokenMinus: Result = -Result; break;
|
||||
case TokenUnaryExor: Result = ~Result; break;
|
||||
case TokenUnaryNot: Result = !Result; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenOpenBracket:
|
||||
if (!ParseExpression(Lexer, Result))
|
||||
ProgramFail(Lexer, "invalid expression");
|
||||
|
||||
if (LexGetToken(Lexer) != TokenCloseBracket)
|
||||
ProgramFail(Lexer, "')' expected");
|
||||
break;
|
||||
|
||||
case TokenAsterisk:
|
||||
case TokenAmpersand:
|
||||
ProgramFail(Lexer, "not implemented");
|
||||
|
||||
case TokenIdentifier:
|
||||
ReadVariable(XXX);
|
||||
break;
|
||||
|
||||
default:
|
||||
*Lexer = PreState;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int ParseExpression(struct LexState *Lexer, struct Value *Result)
|
||||
{
|
||||
struct Value CurrentValue;
|
||||
struct Value TotalValue;
|
||||
|
||||
if (!ParseValue(Lexer, &TotalValue))
|
||||
return FALSE;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
enum LexToken Token = LexPeekToken(Lexer);
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: case TokenMinus: case TokenAsterisk: case TokenSlash:
|
||||
case TokenEquality: case TokenLessThan: case TokenGreaterThan:
|
||||
case TokenLessEqual: case TokenGreaterEqual: case TokenLogicalAnd:
|
||||
case TokenLogicalOr: case TokenArithmeticOr: case TokenArithmeticExor:
|
||||
case TokenDot:
|
||||
LexGetToken(Lexer);
|
||||
break;
|
||||
|
||||
default:
|
||||
*Result = TotalValue;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!ParseValue(Lexer, &CurrentValue))
|
||||
return FALSE;
|
||||
|
||||
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
|
||||
ProgramFail(Lexer, "bad operand types");
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenPlus: TotalValue.Val.Integer += CurrentValue.Val.Integer; break;
|
||||
case TokenMinus: TotalValue.Val.Integer -= CurrentValue.Val.Integer; break;
|
||||
case TokenAsterisk: TotalValue.Val.Integer *= CurrentValue.Val.Integer; break;
|
||||
case TokenSlash: TotalValue.Val.Integer /= CurrentValue.Val.Integer; break;
|
||||
case TokenEquality: TotalValue.Val.Integer = TotalValue.Val.Integer == CurrentValue.Val.Integer; break;
|
||||
case TokenLessThan: TotalValue.Val.Integer = TotalValue.Val.Integer < CurrentValue.Val.Integer; break;
|
||||
case TokenGreaterThan: TotalValue.Val.Integer = TotalValue.Val.Integer > CurrentValue.Val.Integer; break;
|
||||
case TokenLessEqual: TotalValue.Val.Integer = TotalValue.Val.Integer <= CurrentValue.Val.Integer; break;
|
||||
case TokenGreaterEqual: TotalValue.Val.Integer = TotalValue.Val.Integer >= CurrentValue.Val.Integer; break;
|
||||
case TokenLogicalAnd: TotalValue.Val.Integer = TotalValue.Val.Integer && CurrentValue.Val.Integer; break;
|
||||
case TokenLogicalOr: TotalValue.Val.Integer = TotalValue.Val.Integer || CurrentValue.Val.Integer; break;
|
||||
case TokenAmpersand: TotalValue.Val.Integer = TotalValue.Val.Integer & CurrentValue.Val.Integer; break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int ParseStatement(struct LexState *Lexer, int RunIt)
|
||||
{
|
||||
int Conditional;
|
||||
struct LexState PreState = *Lexer;
|
||||
enum LexToken Token = LexGetToken(Lexer);
|
||||
|
||||
switch (Token)
|
||||
{
|
||||
case TokenIdentifier:
|
||||
ParseIdentStatement(&PreState, RunIt);
|
||||
break;
|
||||
|
||||
case TokenLeftBrace:
|
||||
while (ParseStatement(Lexer, RunIt))
|
||||
{}
|
||||
|
||||
if (LexGetToken(Lexer) != TokenRightBrace)
|
||||
ProgramFail(Lexer, "'}' expected");
|
||||
break;
|
||||
|
||||
case TokenIf:
|
||||
if (!ParseIntExpression(Lexer, &Conditional))
|
||||
ProgramFail(Lexer, "expression expected");
|
||||
|
||||
if (!ParseStatement(Lexer, RunIt && Conditional))
|
||||
ProgramFail(Lexer, "statement expected");
|
||||
|
||||
if (LexPeekToken(Lexer) == TokenElse)
|
||||
{
|
||||
LexGetToken(Lexer);
|
||||
if (!ParseStatement(Lexer, RunIt && !Conditional))
|
||||
ProgramFail(Lexer, "statement expected");
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenWhile:
|
||||
{
|
||||
struct LexState PreConditional = *Lexer;
|
||||
do
|
||||
{
|
||||
*Lexer = PreConditional;
|
||||
if (!ParseIntExpression(Lexer, &Conditional))
|
||||
ProgramFail(Lexer, "expression expected");
|
||||
|
||||
if (!ParseStatement(Lexer, RunIt && Conditional))
|
||||
ProgramFail(Lexer, "statement expected");
|
||||
|
||||
} while (Conditional && RunIt);
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenDo:
|
||||
{
|
||||
struct LexState PreStatement = *Lexer;
|
||||
do
|
||||
{
|
||||
*Lexer = PreStatement;
|
||||
if (!ParseStatement(Lexer, RunIt))
|
||||
ProgramFail(Lexer, "statement expected");
|
||||
|
||||
if (!ParseIntExpression(Lexer, &Conditional))
|
||||
ProgramFail(Lexer, "expression expected");
|
||||
|
||||
} while (Conditional && RunIt);
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenFor:
|
||||
{
|
||||
struct LexState PreConditional;
|
||||
struct LexState PreIncrement;
|
||||
struct LexState PreStatement;
|
||||
struct LexState After;
|
||||
|
||||
if (LexGetToken(Lexer) != TokenOpenBracket)
|
||||
ProgramFail(Lexer, "'(' expected");
|
||||
|
||||
if (!ParseStatement(Lexer, RunIt))
|
||||
ProgramFail(Lexer, "statement expected");
|
||||
|
||||
PreConditional = *Lexer;
|
||||
if (!ParseIntExpression(Lexer, &Conditional))
|
||||
ProgramFail(Lexer, "expression expected");
|
||||
|
||||
if (LexGetToken(Lexer) != TokenSemicolon)
|
||||
ProgramFail(Lexer, "';' expected");
|
||||
|
||||
PreIncrement = *Lexer;
|
||||
ParseStatement(Lexer, FALSE);
|
||||
|
||||
if (LexGetToken(Lexer) != TokenCloseBracket)
|
||||
ProgramFail(Lexer, "')' expected");
|
||||
|
||||
PreStatement = *Lexer;
|
||||
if (!ParseStatement(Lexer, Conditional && RunIt))
|
||||
ProgramFail(Lexer, "statement expected");
|
||||
|
||||
After = *Lexer;
|
||||
|
||||
while (Conditional && RunIt)
|
||||
{
|
||||
*Lexer = PreIncrement;
|
||||
ParseStatement(Lexer, TRUE);
|
||||
|
||||
*Lexer = PreConditional;
|
||||
ParseIntExpression(Lexer, &Conditional);
|
||||
|
||||
if (Conditional)
|
||||
{
|
||||
*Lexer = PreStatement;
|
||||
ParseStatement(Lexer, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
*Lexer = After;
|
||||
}
|
||||
break;
|
||||
|
||||
case TokenSemicolon: break;
|
||||
|
||||
case TokenIntType:
|
||||
case TokenCharType:
|
||||
case TokenVoidType:
|
||||
if (LexGetToken(Lexer) != TokenIdentifier)
|
||||
ProgramFail(Lexer, "identifier expected");
|
||||
|
||||
DeclareVariable(Lexer, Lexer->Value.String);
|
||||
break;
|
||||
|
||||
default:
|
||||
*Lexer = PreState;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* parse and run some code */
|
||||
void ParseRun(const Str *FileName, const Str *Source, int LineNo)
|
||||
{
|
||||
enum LexToken Token;
|
||||
struct LexState Lexer;
|
||||
int ParseDepth = 0;
|
||||
int IntValue;
|
||||
|
||||
LexInit(&Lexer, Source, FileName, 1);
|
||||
|
||||
while ( (Token = LexGetToken(&Lexer)) != TokenEOF)
|
||||
{
|
||||
/* do parsey things here */
|
||||
StrPrintf("token %d\n", (int)Token);
|
||||
|
||||
switch (ParseDepth)
|
||||
{
|
||||
case 0: /* top level */
|
||||
if (Token == XXX
|
||||
break;
|
||||
|
||||
case X: /* primary expression */
|
||||
switch (Token)
|
||||
{
|
||||
case TokenIdentifier: IntValue = XXX; GoUp = TRUE; break;
|
||||
case TokenIntegerConstant: IntValue = Lexer->Value.Integer; GoUp = TRUE; break;
|
||||
case TokenStringConstant: StringValue = Lexer->Value.String; GoUp = TRUE; break;
|
||||
case TokenOpenBracket:
|
||||
}
|
||||
}
|
||||
|
||||
while (ParseStatement(Lexer, TRUE))
|
||||
{}
|
||||
}
|
||||
|
||||
/* quick scan a source file for definitions */
|
||||
|
|
15
picoc.h
15
picoc.h
|
@ -60,6 +60,7 @@ enum LexToken
|
|||
TokenArithmeticOr,
|
||||
TokenArithmeticExor,
|
||||
TokenUnaryExor,
|
||||
TokenUnaryNot,
|
||||
TokenComma,
|
||||
TokenDot,
|
||||
TokenAddAssign,
|
||||
|
@ -107,12 +108,24 @@ struct FuncDef
|
|||
int StartLine;
|
||||
};
|
||||
|
||||
enum ValueType
|
||||
{
|
||||
TypeInt,
|
||||
TypeString
|
||||
};
|
||||
|
||||
union AnyValue
|
||||
{
|
||||
int Integer;
|
||||
Str String;
|
||||
};
|
||||
|
||||
struct Value
|
||||
{
|
||||
enum ValueType Typ;
|
||||
union AnyValue Val;
|
||||
};
|
||||
|
||||
/* lexer state - so we can lex nested files */
|
||||
struct LexState
|
||||
{
|
||||
|
@ -135,6 +148,7 @@ void vStrPrintf(const char *Format, va_list Args);
|
|||
/* picoc.c */
|
||||
void Fail(const char *Message, ...);
|
||||
void ProgramError(const Str *FileName, int Line, const char *Message, ...);
|
||||
void ProgramFail(struct LexState *Lexer, const char *Message, ...);
|
||||
void ScanFile(const Str *FileName);
|
||||
|
||||
/* table.c */
|
||||
|
@ -145,6 +159,7 @@ void *TableLookup(struct Table *Tbl, const Str *Key);
|
|||
/* lex.c */
|
||||
void LexInit(struct LexState *Lexer, const Str *Source, const Str *FileName, int Line);
|
||||
enum LexToken LexGetToken(struct LexState *Lexer);
|
||||
enum LexToken LexPeekToken(struct LexState *Lexer);
|
||||
|
||||
/* parse.c */
|
||||
void ParseInit(void);
|
||||
|
|
Loading…
Reference in a new issue