Add new symbols to the parser. They are not currently handled
This commit is contained in:
parent
e44158f3b7
commit
473af8d54e
|
@ -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();
|
||||
|
||||
|
|
57
src/Lexer.c
57
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,7 +273,31 @@ 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 ',':
|
||||
|
@ -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 ';':
|
||||
|
|
21
src/Parser.c
21
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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue
Block a user