Added floating point support
git-svn-id: http://picoc.googlecode.com/svn/trunk@22 21eae674-98b7-11dd-bd71-f92a316d2d60
This commit is contained in:
parent
a8008e9ac7
commit
704f20e1c4
3
Makefile
3
Makefile
|
@ -1,5 +1,6 @@
|
||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS=-Wall -g
|
CFLAGS=-Wall -g
|
||||||
|
LIBS=-lm
|
||||||
|
|
||||||
TARGET = picoc
|
TARGET = picoc
|
||||||
SRCS = picoc.c table.c str.c parse.c lex.c
|
SRCS = picoc.c table.c str.c parse.c lex.c
|
||||||
|
@ -8,7 +9,7 @@ OBJS := $(SRCS:%.c=%.o)
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS)
|
$(TARGET): $(OBJS)
|
||||||
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
|
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LIBS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(TARGET) $(OBJS) *~
|
rm -f $(TARGET) $(OBJS) *~
|
||||||
|
|
26
lex.c
26
lex.c
|
@ -1,4 +1,5 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "picoc.h"
|
#include "picoc.h"
|
||||||
|
|
||||||
|
@ -25,7 +26,9 @@ static struct ReservedWord ReservedWords[] =
|
||||||
{ "char", TokenCharType },
|
{ "char", TokenCharType },
|
||||||
{ "default", TokenDefault },
|
{ "default", TokenDefault },
|
||||||
{ "do", TokenDo },
|
{ "do", TokenDo },
|
||||||
|
{ "double", TokenDoubleType },
|
||||||
{ "else", TokenElse },
|
{ "else", TokenElse },
|
||||||
|
{ "float", TokenFloatType },
|
||||||
{ "for", TokenFor },
|
{ "for", TokenFor },
|
||||||
{ "if", TokenIf },
|
{ "if", TokenIf },
|
||||||
{ "int", TokenIntType },
|
{ "int", TokenIntType },
|
||||||
|
@ -59,15 +62,30 @@ enum LexToken LexCheckReservedWord(const Str *Word)
|
||||||
enum LexToken LexGetNumber(struct LexState *Lexer, union AnyValue *Value)
|
enum LexToken LexGetNumber(struct LexState *Lexer, union AnyValue *Value)
|
||||||
{
|
{
|
||||||
int Result = 0;
|
int Result = 0;
|
||||||
|
double FPResult;
|
||||||
|
double FPDiv;
|
||||||
|
|
||||||
while (Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos))
|
for (; Lexer->Pos != Lexer->End && isdigit(*Lexer->Pos); Lexer->Pos++)
|
||||||
{
|
|
||||||
Result = Result * 10 + (*Lexer->Pos - '0');
|
Result = Result * 10 + (*Lexer->Pos - '0');
|
||||||
Lexer->Pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value->Integer = Result;
|
Value->Integer = Result;
|
||||||
|
if (Lexer->Pos == Lexer->End || *Lexer->Pos != '.')
|
||||||
return TokenIntegerConstant;
|
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)
|
enum LexToken LexGetWord(struct LexState *Lexer, union AnyValue *Value)
|
||||||
|
|
48
parse.c
48
parse.c
|
@ -81,6 +81,7 @@ int ParseType(struct LexState *Lexer, enum ValueType *Typ)
|
||||||
switch (Token)
|
switch (Token)
|
||||||
{
|
{
|
||||||
case TokenIntType: case TokenCharType: *Typ = TypeInt; return TRUE;
|
case TokenIntType: case TokenCharType: *Typ = TypeInt; return TRUE;
|
||||||
|
case TokenFloatType: case TokenDoubleType: *Typ = TypeFP; return TRUE;
|
||||||
case TokenVoidType: *Typ = TypeVoid; return TRUE;
|
case TokenVoidType: *Typ = TypeVoid; return TRUE;
|
||||||
default: *Lexer = Before; return FALSE;
|
default: *Lexer = Before; return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -179,11 +180,9 @@ int ParseValue(struct LexState *Lexer, struct Value *Result, struct Value **LVal
|
||||||
|
|
||||||
switch (Token)
|
switch (Token)
|
||||||
{
|
{
|
||||||
case TokenIntegerConstant: case TokenCharacterConstant: case TokenStringConstant:
|
case TokenIntegerConstant: case TokenCharacterConstant: Result->Typ = TypeInt; break;
|
||||||
Result->Typ = TypeInt;
|
case TokenFPConstant: Result->Typ = TypeFP; break;
|
||||||
if (Token == TokenStringConstant)
|
case TokenStringConstant: Result->Typ = TypeString; break;
|
||||||
Result->Typ = TypeString;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
case TokenMinus: case TokenUnaryExor: case TokenUnaryNot:
|
||||||
ParseIntExpression(Lexer, Result, RunIt);
|
ParseIntExpression(Lexer, Result, RunIt);
|
||||||
|
@ -284,10 +283,42 @@ int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (RunIt)
|
if (RunIt)
|
||||||
|
{
|
||||||
|
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
|
||||||
{
|
{
|
||||||
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
|
if (CurrentValue.Typ != TypeInt || TotalValue.Typ != TypeInt)
|
||||||
ProgramFail(Lexer, "bad operand types");
|
ProgramFail(Lexer, "bad operand types");
|
||||||
|
|
||||||
|
/* integer arithmetic */
|
||||||
switch (Token)
|
switch (Token)
|
||||||
{
|
{
|
||||||
case TokenPlus: TotalValue.Val.Integer += CurrentValue.Val.Integer; break;
|
case TokenPlus: TotalValue.Val.Integer += CurrentValue.Val.Integer; break;
|
||||||
|
@ -309,6 +340,7 @@ int ParseExpression(struct LexState *Lexer, struct Value *Result, int RunIt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -473,6 +505,8 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
|
||||||
|
|
||||||
case TokenIntType:
|
case TokenIntType:
|
||||||
case TokenCharType:
|
case TokenCharType:
|
||||||
|
case TokenFloatType:
|
||||||
|
case TokenDoubleType:
|
||||||
case TokenVoidType:
|
case TokenVoidType:
|
||||||
*Lexer = PreState;
|
*Lexer = PreState;
|
||||||
ParseType(Lexer, &Typ);
|
ParseType(Lexer, &Typ);
|
||||||
|
@ -485,7 +519,11 @@ int ParseStatement(struct LexState *Lexer, int RunIt)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct Value InitValue;
|
struct Value InitValue;
|
||||||
|
if (Typ == TokenFloatType)
|
||||||
|
InitValue.Val.FP = 0.0;
|
||||||
|
else
|
||||||
InitValue.Val.Integer = 0;
|
InitValue.Val.Integer = 0;
|
||||||
|
|
||||||
InitValue.Typ = Typ;
|
InitValue.Typ = Typ;
|
||||||
VariableDefine(Lexer, &LexerValue.String, &InitValue);
|
VariableDefine(Lexer, &LexerValue.String, &InitValue);
|
||||||
}
|
}
|
||||||
|
|
5
picoc.h
5
picoc.h
|
@ -37,6 +37,7 @@ enum LexToken
|
||||||
TokenEOF,
|
TokenEOF,
|
||||||
TokenIdentifier,
|
TokenIdentifier,
|
||||||
TokenIntegerConstant,
|
TokenIntegerConstant,
|
||||||
|
TokenFPConstant,
|
||||||
TokenStringConstant,
|
TokenStringConstant,
|
||||||
TokenCharacterConstant,
|
TokenCharacterConstant,
|
||||||
TokenType,
|
TokenType,
|
||||||
|
@ -73,6 +74,8 @@ enum LexToken
|
||||||
TokenDecrement,
|
TokenDecrement,
|
||||||
TokenIntType,
|
TokenIntType,
|
||||||
TokenCharType,
|
TokenCharType,
|
||||||
|
TokenFloatType,
|
||||||
|
TokenDoubleType,
|
||||||
TokenVoidType,
|
TokenVoidType,
|
||||||
TokenDo,
|
TokenDo,
|
||||||
TokenElse,
|
TokenElse,
|
||||||
|
@ -106,6 +109,7 @@ enum ValueType
|
||||||
{
|
{
|
||||||
TypeVoid,
|
TypeVoid,
|
||||||
TypeInt,
|
TypeInt,
|
||||||
|
TypeFP,
|
||||||
TypeString,
|
TypeString,
|
||||||
TypeFunction
|
TypeFunction
|
||||||
};
|
};
|
||||||
|
@ -113,6 +117,7 @@ enum ValueType
|
||||||
union AnyValue
|
union AnyValue
|
||||||
{
|
{
|
||||||
int Integer;
|
int Integer;
|
||||||
|
double FP;
|
||||||
Str String;
|
Str String;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue