Added floating point support

git-svn-id: http://picoc.googlecode.com/svn/trunk@22 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
zik.saleeba 2008-12-27 02:25:49 +00:00
parent a8008e9ac7
commit 704f20e1c4
4 changed files with 95 additions and 33 deletions

View file

@ -1,5 +1,6 @@
CC=gcc
CFLAGS=-Wall -g
LIBS=-lm
TARGET = picoc
SRCS = picoc.c table.c str.c parse.c lex.c
@ -8,7 +9,7 @@ OBJS := $(SRCS:%.c=%.o)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
clean:
rm -f $(TARGET) $(OBJS) *~

30
lex.c
View file

@ -1,4 +1,5 @@
#include <ctype.h>
#include <math.h>
#include "picoc.h"
@ -25,7 +26,9 @@ static struct ReservedWord ReservedWords[] =
{ "char", TokenCharType },
{ "default", TokenDefault },
{ "do", TokenDo },
{ "double", TokenDoubleType },
{ "else", TokenElse },
{ "float", TokenFloatType },
{ "for", TokenFor },
{ "if", TokenIf },
{ "int", TokenIntType },
@ -59,15 +62,30 @@ enum LexToken LexCheckReservedWord(const Str *Word)
enum LexToken LexGetNumber(struct LexState *Lexer, union AnyValue *Value)
{
int Result = 0;
double FPResult;
double FPDiv;
while (Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos))
{
Result = Result * 10 + (*Lexer->Pos - '0');
Lexer->Pos++;
}
for (; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++)
Result = Result * 10 + (*Lexer->Pos - '0');
Value->Integer = Result;
return TokenIntegerConstant;
if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.')
return TokenIntegerConstant;
Lexer->Pos++;
for (FPDiv = 0.1, FPResult = (double)Result; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++, FPDiv /= 10.0)
FPResult += (*Lexer->Pos - '0') * FPDiv;
if (Lexer->Pos != Lexer->End && (*Lexer->Pos == 'e' || *Lexer->Pos == 'E'))
{
Lexer->Pos++;
for (Result = 0; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++)
Result = Result * 10 + (*Lexer->Pos - '0');
FPResult *= pow(10.0, (double)Result);
}
return TokenFPConstant;
}
enum LexToken LexGetWord(struct LexState *Lexer, union AnyValue *Value)

90
parse.c
View file

@ -81,6 +81,7 @@ int ParseType(struct LexState *Lexer, enum ValueType *Typ)
switch (Token)
{
case TokenIntType: case TokenCharType: *Typ = TypeInt; return TRUE;
case TokenFloatType: case TokenDoubleType: *Typ = TypeFP; return TRUE;
case TokenVoidType: *Typ = TypeVoid; return TRUE;
default: *Lexer = Before; return FALSE;
}
@ -179,11 +180,9 @@ int ParseValue(struct LexState *Lexer, struct Value *Result, struct Value **LVal
switch (Token)
{
case TokenIntegerConstant: case TokenCharacterConstant: case TokenStringConstant:
Result->Typ = TypeInt;
if (Token == TokenStringConstant)
Result->Typ = TypeString;
break;
case TokenIntegerConstant: case TokenCharacterConstant: Result->Typ = TypeInt; break;
case TokenFPConstant: Result->Typ = TypeFP; break;
case TokenStringConstant: Result->Typ = TypeString; break;
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
ParseIntExpression(Lexer, Result, RunIt);
@ -285,27 +284,60 @@ int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt)
if (RunIt)
{
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
ProgramFail(Lexer, "bad operand types");
switch (Token)
if (CurrentValue.Typ == TypeFP || TotalValue.Typ == TypeFP)
{ /* convert both to floating point */
if (CurrentValue.Typ == TypeInt)
CurrentValue.Val.FP = (double)CurrentValue.Val.Integer;
else if (CurrentValue.Typ != TypeFP)
ProgramFail(Lexer, "bad type for operator");
if (TotalValue.Typ == TypeInt)
TotalValue.Val.FP = (double)TotalValue.Val.Integer;
else if (TotalValue.Typ != TypeFP)
ProgramFail(Lexer, "bad type for operator");
TotalValue.Typ = TypeInt;
switch (Token)
{
case TokenPlus: TotalValue.Val.FP += CurrentValue.Val.FP; TotalValue.Typ = TypeFP; break;
case TokenMinus: TotalValue.Val.FP -= CurrentValue.Val.FP; TotalValue.Typ = TypeFP; break;
case TokenAsterisk: TotalValue.Val.FP *= CurrentValue.Val.FP; TotalValue.Typ = TypeFP; break;
case TokenSlash: TotalValue.Val.FP /= CurrentValue.Val.FP; TotalValue.Typ = TypeFP; break;
case TokenEquality: TotalValue.Val.Integer = TotalValue.Val.FP == CurrentValue.Val.FP; break;
case TokenLessThan: TotalValue.Val.Integer = TotalValue.Val.FP < CurrentValue.Val.FP; break;
case TokenGreaterThan: TotalValue.Val.Integer = TotalValue.Val.FP > CurrentValue.Val.FP; break;
case TokenLessEqual: TotalValue.Val.Integer = TotalValue.Val.FP <= CurrentValue.Val.FP; break;
case TokenGreaterEqual: TotalValue.Val.Integer = TotalValue.Val.FP >= CurrentValue.Val.FP; break;
case TokenLogicalAnd: case TokenLogicalOr: case TokenAmpersand: case TokenArithmeticOr: case TokenArithmeticExor: ProgramFail(Lexer, "bad type for operator"); break;
case TokenDot: ProgramFail(Lexer, "operator not supported"); break;
default: break;
}
}
else
{
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: printf("compare %d <= %d\n", TotalValue.Val.Integer, CurrentValue.Val.Integer); 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;
default: break;
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
ProgramFail(Lexer, "bad operand types");
/* integer arithmetic */
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: printf("compare %d <= %d\n", TotalValue.Val.Integer, CurrentValue.Val.Integer); 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;
default: break;
}
}
}
}
@ -473,6 +505,8 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
case TokenIntType:
case TokenCharType:
case TokenFloatType:
case TokenDoubleType:
case TokenVoidType:
*Lexer = PreState;
ParseType(Lexer, &Typ);
@ -485,7 +519,11 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
else
{
struct Value InitValue;
InitValue.Val.Integer = 0;
if (Typ == TokenFloatType)
InitValue.Val.FP = 0.0;
else
InitValue.Val.Integer = 0;
InitValue.Typ = Typ;
VariableDefine(Lexer, &LexerValue.String, &InitValue);
}

View file

@ -37,6 +37,7 @@ enum LexToken
TokenEOF,
TokenIdentifier,
TokenIntegerConstant,
TokenFPConstant,
TokenStringConstant,
TokenCharacterConstant,
TokenType,
@ -73,6 +74,8 @@ enum LexToken
TokenDecrement,
TokenIntType,
TokenCharType,
TokenFloatType,
TokenDoubleType,
TokenVoidType,
TokenDo,
TokenElse,
@ -106,6 +109,7 @@ enum ValueType
{
TypeVoid,
TypeInt,
TypeFP,
TypeString,
TypeFunction
};
@ -113,6 +117,7 @@ enum ValueType
union AnyValue
{
int Integer;
double FP;
Str String;
};