From 704f20e1c4fe3b71c3b1b5059e0d03b4f27634c6 Mon Sep 17 00:00:00 2001 From: "zik.saleeba" Date: Sat, 27 Dec 2008 02:25:49 +0000 Subject: [PATCH] Added floating point support git-svn-id: http://picoc.googlecode.com/svn/trunk@22 21eae674-98b7-11dd-bd71-f92a316d2d60 --- Makefile | 3 +- lex.c | 30 +++++++++++++++---- parse.c | 90 ++++++++++++++++++++++++++++++++++++++++---------------- picoc.h | 5 ++++ 4 files changed, 95 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index c358fc2..7be651c 100644 --- a/Makefile +++ b/Makefile @@ -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) *~ diff --git a/lex.c b/lex.c index cc4a112..8ff44ef 100644 --- a/lex.c +++ b/lex.c @@ -1,4 +1,5 @@ #include +#include #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) diff --git a/parse.c b/parse.c index e49f0a7..2aac2fa 100644 --- a/parse.c +++ b/parse.c @@ -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); } diff --git a/picoc.h b/picoc.h index 5ecf89e..7c9aaa5 100644 --- a/picoc.h +++ b/picoc.h @@ -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; };