From 473af8d54ee7880866ca19f28193f7987f0f14e6 Mon Sep 17 00:00:00 2001 From: Curle Date: Mon, 23 Nov 2020 21:42:32 +0000 Subject: [PATCH] Add new symbols to the parser. They are not currently handled --- include/Defs.h | 10 +++--- src/Lexer.c | 57 +++++++++++++++++++++++++++++++--- src/Parser.c | 21 +------------ src/Statements.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 137 insertions(+), 30 deletions(-) diff --git a/include/Defs.h b/include/Defs.h index 9e440cc..08b676a 100644 --- a/include/Defs.h +++ b/include/Defs.h @@ -60,7 +60,7 @@ enum TokenTypes { BOOL_INVERT, // Boolean Invert (!) - BIT_NOT, // Bitwise NOT (¬) + BIT_NOT, // Bitwise NOT (~) LI_INT, // Integer literal LI_STR, // String literal @@ -75,7 +75,6 @@ enum TokenTypes { LI_LPARE, // ( LI_RPARE, // ) - LI_AMP, // & LI_COM, // , TY_IDENTIFIER, // Identifier name. Variable, function, etc. @@ -132,8 +131,10 @@ enum SyntaxOps { OP_MULTIPLY, // Multiply two numbers. OP_DIVIDE, // Divide two numbers. - OP_INCREMENT, // Increment a number (pre or postfix) - OP_DECREMENT, // Decrement a number (pre or postfix) + OP_PREINC, // Increment var before reference. + OP_PREDEC, // Decrement var before reference. + OP_POSTINC, // Increment var after reference. + OP_POSTDEC, // Decrement var after reference. OP_BITNOT, // Invert a number bitwise OP_BOOLNOT, // Invert a statement @@ -281,6 +282,7 @@ struct ASTNode* ParsePrimary(void); //void ParseStatements(void); struct ASTNode* ParseStatement(void); struct ASTNode* PrefixStatement(); +struct ASTNode* PostfixStatement(); void ParseGlobals(); diff --git a/src/Lexer.c b/src/Lexer.c index 9767aa5..62e823a 100644 --- a/src/Lexer.c +++ b/src/Lexer.c @@ -243,11 +243,25 @@ int Tokenise(struct Token* Token) { return 0; case '+': - Token->type = AR_PLUS; + // + can be either "+" or "++". + Char = NextChar(); + if(Char == '+') { + Token->type = PPMM_PLUS; + } else { + Token->type = AR_PLUS; + ReturnCharToStream(Char); + } break; case '-': - Token->type = AR_MINUS; + // - can be either "-" or "--" + Char = NextChar(); + if(Char == '-') { + Token->type = PPMM_MINUS; + } else { + Token->type = AR_MINUS; + ReturnCharToStream(Char); + } break; case '*': @@ -259,9 +273,33 @@ int Tokenise(struct Token* Token) { break; case '&': - Token->type = LI_AMP; + Char = NextChar(); + if(Char == '&') { + Token->type = BOOL_AND; + } else { + Token->type = BIT_AND; + ReturnCharToStream(Char); + } break; + case '|': + Char = NextChar(); + if(Char == '|') { + Token->type = BOOL_OR; + } else { + Token->type = BIT_OR; + ReturnCharToStream(Char); + } + break; + + case '^': + Token->type = BIT_XOR; + break; + + case '~': + Token->type = BIT_NOT; + break; + case ',': Token->type = LI_COM; break; @@ -288,6 +326,7 @@ int Tokenise(struct Token* Token) { Token->type = CMP_INEQ; // Otherwise, we have a spare char } else { + Token->type = BOOL_INVERT; ReturnCharToStream(Char); } break; @@ -297,6 +336,8 @@ int Tokenise(struct Token* Token) { // If the next char is =, we have <=, the less than or equal comparator. if(Char == '=') { Token->type = CMP_LTE; + } else if(Char == '<') { // But if the next char is <, we have << - the Shift Left operator. + Token->type = SH_LEFT; } else { ReturnCharToStream(Char); Token->type = CMP_LT; @@ -304,8 +345,14 @@ int Tokenise(struct Token* Token) { break; case '>': - // There is no special casing for >. Less than or equal is => - Token->type = CMP_GT; + // For >, Less than or equal is => so we can ignore it, but the Shift Right operator is >>. + Char = NextChar(); + if(Char == '>') { + Token->type = SH_RIGHT; + } else { + Token->type = CMP_GT; + ReturnCharToStream(Char); + } break; case ';': diff --git a/src/Parser.c b/src/Parser.c index d790a99..6690218 100644 --- a/src/Parser.c +++ b/src/Parser.c @@ -128,26 +128,7 @@ struct ASTNode* ParsePrimary(void) { break; case TY_IDENTIFIER: - // A variable or a function? - - // Read the next token - Tokenise(&CurrentToken); - - // If the token after the identifier is a (, then it's a function. - if(CurrentToken.type == LI_LPARE) - return CallFunction(); - - if(CurrentToken.type == LI_LBRAS) - return AccessArray(); - - // Otherwise, we've read too far and need to go back. - RejectToken(&CurrentToken); - // It's a variable, so find the symbol and construct a leaf for it - ID = FindSymbol(CurrentIdentifier); - if(ID == -1) - DieMessage("Unknown Variable", CurrentIdentifier); - Node = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID); - break; + return PostfixStatement(); case LI_RPARE: // Starting a ( expr ) block diff --git a/src/Statements.c b/src/Statements.c index 54fd8c7..6e8396c 100644 --- a/src/Statements.c +++ b/src/Statements.c @@ -301,11 +301,88 @@ struct ASTNode* PrintStatement(void) { } +struct ASTNode* PostfixStatement() { + struct ASTNode* Tree; + int ID; + + Tokenise(&CurrentToken); + + // If we get here, we're one of three things: + // - Function + // - Array + // - Variable + + if(CurrentToken.type == LI_LPARE) + return CallFunction(); + + if(CurrentToken.type == LI_LBRAS) + return AccessArray(); + + // If we get here, we must be a variable. + // There's no guarantees that the variable is in + // the symbol table, though. + + ID = FindSymbol(CurrentIdentifier); + if(ID == -1 || Symbols[ID].Structure != ST_VAR) + DieMessage("Unknown Variable", CurrentIdentifier); + + // Here we check for postincrement and postdecrement. + + switch(CurrentToken.type) { + case PPMM_PLUS: + Tokenise(&CurrentToken); + Tree = ConstructASTLeaf(OP_POSTINC, Symbols[ID].Type, ID); + break; + case PPMM_MINUS: + Tokenise(&CurrentToken); + Tree = ConstructASTLeaf(OP_POSTDEC, Symbols[ID].Type, ID); + break; + default: + Tree = ConstructASTLeaf(REF_IDENT, Symbols[ID].Type, ID); + } + + return Tree; + +} + struct ASTNode* PrefixStatement() { struct ASTNode* Tree; switch (CurrentToken.type) { - case LI_AMP: + case BOOL_INVERT: + Tokenise(&CurrentToken); + Tree = PrefixStatement(); + Tree->RVal = 1; + Tree = ConstructASTBranch(OP_BOOLNOT, Tree->ExprType, Tree, 0); + break; + + case BIT_NOT: + Tokenise(&CurrentToken); + Tree = PrefixStatement(); + Tree->RVal = 1; + Tree = ConstructASTBranch(OP_BITNOT, Tree->ExprType, Tree, 0); + break; + + case PPMM_PLUS: + Tokenise(&CurrentToken); + Tree = PrefixStatement(); + + if(Tree->Operation != REF_IDENT) + Die("++ not followed by identifier"); + Tree = ConstructASTBranch(OP_PREINC, Tree->ExprType, Tree, 0); + break; + + case PPMM_MINUS: + Tokenise(&CurrentToken); + Tree = PrefixStatement(); + + if(Tree->Operation != REF_IDENT) + Die("-- not followed by identifier"); + + Tree = ConstructASTBranch(OP_PREDEC, Tree->ExprType, Tree, 0); + break; + + case BIT_AND: Tokenise(&CurrentToken); // To allow things like: