mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Expression statements and assignemnts are working
This commit is contained in:
@@ -52,18 +52,20 @@ print [:];
|
|||||||
//test nested compounds
|
//test nested compounds
|
||||||
print [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
print [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
|
||||||
|
|
||||||
//not ready yet
|
//var declarations
|
||||||
var x = 31;
|
var x = 31;
|
||||||
var y : int = 42;
|
var y : int = 42;
|
||||||
var arr : [int] = [1, 2, 3, 42];
|
var arr : [int] = [1, 2, 3, 42];
|
||||||
var dict : [string, int] = ["hello": 1, "world":2];
|
var dict : [string, int] = ["hello": 1, "world":2];
|
||||||
|
|
||||||
//print x;
|
//printing expressions
|
||||||
//print x + y;
|
print x;
|
||||||
//print arr;
|
print x + y;
|
||||||
//print dict;
|
print arr;
|
||||||
|
print dict;
|
||||||
|
|
||||||
//test asserts at the end of the file
|
//test asserts at the end of the file
|
||||||
|
assert x, "This won't be seen";
|
||||||
assert true, "This won't be seen";
|
assert true, "This won't be seen";
|
||||||
assert false, "This is a failed assert, and will end execution";
|
assert false, "This is a failed assert, and will end execution";
|
||||||
|
|
||||||
|
|||||||
@@ -110,13 +110,27 @@ static void consumeShort(unsigned short bytes, unsigned char* tb, int* count) {
|
|||||||
*count += 2;
|
*count += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Literal parseIdentifierToValue(Interpreter* interpreter, Literal literal) {
|
||||||
|
//this converts identifiers to values
|
||||||
|
if (IS_IDENTIFIER(literal)) {
|
||||||
|
if (!getScopeVariable(interpreter->scope, literal, &literal)) {
|
||||||
|
printf("Undeclared variable \"");;
|
||||||
|
printLiteral(literal);
|
||||||
|
printf("\"\n");
|
||||||
|
return TO_NULL_LITERAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
//each available statement
|
//each available statement
|
||||||
static bool execAssert(Interpreter* interpreter) {
|
static bool execAssert(Interpreter* interpreter) {
|
||||||
Literal rhs = popLiteralArray(&interpreter->stack);
|
Literal rhs = popLiteralArray(&interpreter->stack);
|
||||||
Literal lhs = popLiteralArray(&interpreter->stack);
|
Literal lhs = parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack));
|
||||||
|
|
||||||
if (!IS_STRING(rhs)) {
|
if (!IS_STRING(rhs)) {
|
||||||
printf("[internal] The interpreter's assert keyword needs a string as the second argument, received: ");
|
printf("The assert keyword needs a string as the second argument, received: ");
|
||||||
printLiteral(rhs);
|
printLiteral(rhs);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -132,7 +146,7 @@ static bool execAssert(Interpreter* interpreter) {
|
|||||||
|
|
||||||
static bool execPrint(Interpreter* interpreter) {
|
static bool execPrint(Interpreter* interpreter) {
|
||||||
//print what is on top of the stack, then pop it
|
//print what is on top of the stack, then pop it
|
||||||
Literal lit = popLiteralArray(&interpreter->stack);
|
Literal lit = parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack));
|
||||||
|
|
||||||
printLiteralCustom(lit, interpreter->printOutput);
|
printLiteralCustom(lit, interpreter->printOutput);
|
||||||
|
|
||||||
@@ -152,7 +166,7 @@ static bool execPushLiteral(Interpreter* interpreter, bool lng) {
|
|||||||
index = (int)readByte(interpreter->bytecode, &interpreter->count);
|
index = (int)readByte(interpreter->bytecode, &interpreter->count);
|
||||||
}
|
}
|
||||||
|
|
||||||
//push from cache to stack
|
//push from cache to stack (DO NOT account for identifiers - will do that later)
|
||||||
pushLiteralArray(&interpreter->stack, interpreter->literalCache.literals[index]);
|
pushLiteralArray(&interpreter->stack, interpreter->literalCache.literals[index]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -160,7 +174,7 @@ static bool execPushLiteral(Interpreter* interpreter, bool lng) {
|
|||||||
|
|
||||||
static bool execNegate(Interpreter* interpreter) {
|
static bool execNegate(Interpreter* interpreter) {
|
||||||
//negate the top literal on the stack
|
//negate the top literal on the stack
|
||||||
Literal lit = popLiteralArray(&interpreter->stack);
|
Literal lit = parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack));
|
||||||
|
|
||||||
if (IS_INTEGER(lit)) {
|
if (IS_INTEGER(lit)) {
|
||||||
lit = TO_INTEGER_LITERAL(-AS_INTEGER(lit));
|
lit = TO_INTEGER_LITERAL(-AS_INTEGER(lit));
|
||||||
@@ -180,8 +194,8 @@ static bool execNegate(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool execArithmetic(Interpreter* interpreter, Opcode opcode) {
|
static bool execArithmetic(Interpreter* interpreter, Opcode opcode) {
|
||||||
Literal rhs = popLiteralArray(&interpreter->stack);
|
Literal rhs = parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack));
|
||||||
Literal lhs = popLiteralArray(&interpreter->stack);
|
Literal lhs = parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack));
|
||||||
|
|
||||||
//type coersion
|
//type coersion
|
||||||
if (IS_FLOAT(lhs) && IS_INTEGER(rhs)) {
|
if (IS_FLOAT(lhs) && IS_INTEGER(rhs)) {
|
||||||
@@ -264,7 +278,11 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//wrong types
|
//wrong types
|
||||||
printf("Bad arithmetic argument\n");
|
printf("Bad arithmetic argument ");
|
||||||
|
printLiteral(lhs);
|
||||||
|
printf(" and ");
|
||||||
|
printLiteral(rhs);
|
||||||
|
printf("\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,19 +304,35 @@ static bool execVarDecl(Interpreter* interpreter, bool lng) {
|
|||||||
Literal type = interpreter->literalCache.literals[typeIndex];
|
Literal type = interpreter->literalCache.literals[typeIndex];
|
||||||
|
|
||||||
if (!declareScopeVariable(interpreter->scope, identifier, type)) {
|
if (!declareScopeVariable(interpreter->scope, identifier, type)) {
|
||||||
printf("Can't redefine the variable \"");;
|
printf("Can't redefine the variable \"");;
|
||||||
printLiteral(identifier);
|
printLiteral(identifier);
|
||||||
printf("\"\n");
|
printf("\"\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setScopeVariable(interpreter->scope, identifier, popLiteralArray(&interpreter->stack) )) {
|
if (!setScopeVariable(interpreter->scope, identifier, parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack)) )) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool execVarAssign(Interpreter* interpreter) {
|
||||||
|
Literal rhs = parseIdentifierToValue(interpreter, popLiteralArray(&interpreter->stack));
|
||||||
|
Literal lhs = popLiteralArray(&interpreter->stack);
|
||||||
|
|
||||||
|
if (!IS_IDENTIFIER(lhs)) {
|
||||||
|
printf("Can't assign to a non-variable \"");;
|
||||||
|
printLiteral(lhs);
|
||||||
|
printf("\"\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setScopeVariable(interpreter->scope, lhs, rhs);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//the heart of toy
|
//the heart of toy
|
||||||
static void execInterpreter(Interpreter* interpreter) {
|
static void execInterpreter(Interpreter* interpreter) {
|
||||||
unsigned char opcode = readByte(interpreter->bytecode, &interpreter->count);
|
unsigned char opcode = readByte(interpreter->bytecode, &interpreter->count);
|
||||||
@@ -365,6 +399,12 @@ static void execInterpreter(Interpreter* interpreter) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_VAR_ASSIGN:
|
||||||
|
if (!execVarAssign(interpreter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unknown opcode found %d, terminating\n", opcode);
|
printf("Unknown opcode found %d, terminating\n", opcode);
|
||||||
printLiteralArray(&interpreter->stack, "\n");
|
printLiteralArray(&interpreter->stack, "\n");
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ typedef struct Interpreter {
|
|||||||
unsigned char* bytecode;
|
unsigned char* bytecode;
|
||||||
int length;
|
int length;
|
||||||
int count;
|
int count;
|
||||||
LiteralArray literalCache; //read-only - built from the bytecode
|
LiteralArray literalCache; //read-only - built from the bytecode, refreshed each time new bytecode is provided
|
||||||
|
|
||||||
//operation
|
//operation
|
||||||
Scope* scope;
|
Scope* scope;
|
||||||
|
|||||||
@@ -28,9 +28,10 @@ typedef enum Opcode {
|
|||||||
OP_TYPE_DECL, //declare a type to be used (as a literal)
|
OP_TYPE_DECL, //declare a type to be used (as a literal)
|
||||||
OP_TYPE_DECL_LONG, //declare a type to be used (as a long literal)
|
OP_TYPE_DECL_LONG, //declare a type to be used (as a long literal)
|
||||||
|
|
||||||
OP_VAR_DECL,
|
OP_VAR_DECL, //declare a variable to be used (as a literal)
|
||||||
OP_VAR_DECL_LONG,
|
OP_VAR_DECL_LONG, //declare a variable to be used (as a long literal)
|
||||||
// OP_VAR_ASSIGN, //stack: literal name, literal value
|
|
||||||
|
OP_VAR_ASSIGN, //assign to a literal
|
||||||
|
|
||||||
//meta
|
//meta
|
||||||
OP_SECTION_END,
|
OP_SECTION_END,
|
||||||
|
|||||||
@@ -300,6 +300,11 @@ static Opcode binary(Parser* parser, Node** nodeHandle, bool canBeAssigned) {
|
|||||||
return OP_MODULO;
|
return OP_MODULO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TOKEN_ASSIGN: {
|
||||||
|
parsePrecedence(parser, nodeHandle, PREC_ASSIGNMENT);
|
||||||
|
return OP_VAR_ASSIGN;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error(parser, parser->previous, "Unexpected token passed to binary precedence rule");
|
error(parser, parser->previous, "Unexpected token passed to binary precedence rule");
|
||||||
return OP_EOF;
|
return OP_EOF;
|
||||||
@@ -384,6 +389,17 @@ static Opcode atomic(Parser* parser, Node** nodeHandle, bool canBeAssigned) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Opcode identifier(Parser* parser, Node** nodeHandle, bool canBeAssigned) {
|
||||||
|
//make a copy of the string
|
||||||
|
Token identifierToken = parser->previous;
|
||||||
|
char* cpy = copyString(identifierToken.lexeme, identifierToken.length);
|
||||||
|
Literal identifier = _toIdentifierLiteral(cpy, strlen(cpy)); //BUGFIX: use this instead of the macro
|
||||||
|
|
||||||
|
emitNodeLiteral(nodeHandle, identifier);
|
||||||
|
|
||||||
|
return OP_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
ParseRule parseRules[] = { //must match the token types
|
ParseRule parseRules[] = { //must match the token types
|
||||||
//types
|
//types
|
||||||
{atomic, NULL, PREC_PRIMARY},// TOKEN_NULL,
|
{atomic, NULL, PREC_PRIMARY},// TOKEN_NULL,
|
||||||
@@ -419,7 +435,7 @@ ParseRule parseRules[] = { //must match the token types
|
|||||||
{NULL, NULL, PREC_NONE},// TOKEN_WHILE,
|
{NULL, NULL, PREC_NONE},// TOKEN_WHILE,
|
||||||
|
|
||||||
//literal values
|
//literal values
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_IDENTIFIER,
|
{identifier, NULL, PREC_PRIMARY},// TOKEN_IDENTIFIER,
|
||||||
{atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_TRUE,
|
{atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_TRUE,
|
||||||
{atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_FALSE,
|
{atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_FALSE,
|
||||||
{atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_INTEGER,
|
{atomic, NULL, PREC_PRIMARY},// TOKEN_LITERAL_INTEGER,
|
||||||
@@ -439,6 +455,7 @@ ParseRule parseRules[] = { //must match the token types
|
|||||||
{NULL, NULL, PREC_NONE},// TOKEN_MODULO_ASSIGN,
|
{NULL, NULL, PREC_NONE},// TOKEN_MODULO_ASSIGN,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_PLUS_PLUS,
|
{NULL, NULL, PREC_NONE},// TOKEN_PLUS_PLUS,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_MINUS_MINUS,
|
{NULL, NULL, PREC_NONE},// TOKEN_MINUS_MINUS,
|
||||||
|
{NULL, binary, PREC_ASSIGNMENT},// TOKEN_ASSIGN,
|
||||||
|
|
||||||
//logical operators
|
//logical operators
|
||||||
{grouping, NULL, PREC_CALL},// TOKEN_PAREN_LEFT,
|
{grouping, NULL, PREC_CALL},// TOKEN_PAREN_LEFT,
|
||||||
@@ -458,7 +475,6 @@ ParseRule parseRules[] = { //must match the token types
|
|||||||
{NULL, NULL, PREC_NONE},// TOKEN_OR,
|
{NULL, NULL, PREC_NONE},// TOKEN_OR,
|
||||||
|
|
||||||
//other operators
|
//other operators
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_ASSIGN,
|
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_COLON,
|
{NULL, NULL, PREC_NONE},// TOKEN_COLON,
|
||||||
{NULL, NULL, PREC_NONE},// TOKEN_SEMICOLON,
|
{NULL, NULL, PREC_NONE},// TOKEN_SEMICOLON,
|
||||||
{NULL, NULL, PREC_CALL},// TOKEN_COMMA,
|
{NULL, NULL, PREC_CALL},// TOKEN_COMMA,
|
||||||
@@ -650,26 +666,26 @@ static void expression(Parser* parser, Node** nodeHandle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//statements
|
//statements
|
||||||
static void blockStmt(Parser* parser, Node* node) {
|
static void blockStmt(Parser* parser, Node** nodeHandle) {
|
||||||
//init
|
//init
|
||||||
node->type = NODE_BLOCK;
|
(*nodeHandle)->type = NODE_BLOCK;
|
||||||
node->block.nodes = NULL;
|
(*nodeHandle)->block.nodes = NULL;
|
||||||
node->block.capacity = 0;
|
(*nodeHandle)->block.capacity = 0;
|
||||||
node->block.count = 0;
|
(*nodeHandle)->block.count = 0;
|
||||||
|
|
||||||
//sub-scope, compile it and push it up in a node
|
//sub-scope, compile it and push it up in a node
|
||||||
while (!match(parser, TOKEN_BRACE_RIGHT)) {
|
while (!match(parser, TOKEN_BRACE_RIGHT)) {
|
||||||
if (node->block.capacity < node->block.count + 1) {
|
if ((*nodeHandle)->block.capacity < (*nodeHandle)->block.count + 1) {
|
||||||
int oldCapacity = node->block.capacity;
|
int oldCapacity = (*nodeHandle)->block.capacity;
|
||||||
|
|
||||||
node->block.capacity = GROW_CAPACITY(oldCapacity);
|
(*nodeHandle)->block.capacity = GROW_CAPACITY(oldCapacity);
|
||||||
node->block.nodes = GROW_ARRAY(Node, node->block.nodes, oldCapacity, node->block.capacity);
|
(*nodeHandle)->block.nodes = GROW_ARRAY(Node, (*nodeHandle)->block.nodes, oldCapacity, (*nodeHandle)->block.capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//use the next node in sequence
|
//use the next node in sequence
|
||||||
node->block.nodes[node->block.count].type = NODE_ERROR; //BUGFIX: so freeing won't break the damn thing
|
(*nodeHandle)->block.nodes[(*nodeHandle)->block.count].type = NODE_ERROR; //BUGFIX: so freeing won't break the damn thing
|
||||||
|
|
||||||
Node* ptr = &(node->block.nodes[node->block.count++]);
|
Node* ptr = &((*nodeHandle)->block.nodes[(*nodeHandle)->block.count++]);
|
||||||
|
|
||||||
//process the grammar rule for this line
|
//process the grammar rule for this line
|
||||||
declaration(parser, &ptr);
|
declaration(parser, &ptr);
|
||||||
@@ -681,53 +697,54 @@ static void blockStmt(Parser* parser, Node* node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printStmt(Parser* parser, Node* node) {
|
static void printStmt(Parser* parser, Node** nodeHandle) {
|
||||||
//set the node info
|
//set the node info
|
||||||
node->type = NODE_UNARY;
|
(*nodeHandle)->type = NODE_UNARY;
|
||||||
node->unary.opcode = OP_PRINT;
|
(*nodeHandle)->unary.opcode = OP_PRINT;
|
||||||
expression(parser, &(node->unary.child));
|
expression(parser, &((*nodeHandle)->unary.child));
|
||||||
|
|
||||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of print statement");
|
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of print statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void assertStmt(Parser* parser, Node* node) {
|
static void assertStmt(Parser* parser, Node** nodeHandle) {
|
||||||
//set the node info
|
//set the node info
|
||||||
node->type = NODE_BINARY;
|
(*nodeHandle)->type = NODE_BINARY;
|
||||||
node->unary.opcode = OP_ASSERT;
|
(*nodeHandle)->unary.opcode = OP_ASSERT;
|
||||||
|
|
||||||
parsePrecedence(parser, &(node->binary.left), PREC_PRIMARY);
|
parsePrecedence(parser, &((*nodeHandle)->binary.left), PREC_PRIMARY);
|
||||||
consume(parser, TOKEN_COMMA, "Expected ',' in assert statement");
|
consume(parser, TOKEN_COMMA, "Expected ',' in assert statement");
|
||||||
parsePrecedence(parser, &(node->binary.right), PREC_PRIMARY);
|
parsePrecedence(parser, &((*nodeHandle)->binary.right), PREC_PRIMARY);
|
||||||
|
|
||||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of assert statement");
|
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of assert statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
//precedence functions
|
//precedence functions
|
||||||
static void expressionStmt(Parser* parser, Node* node) {
|
static void expressionStmt(Parser* parser, Node** nodeHandle) {
|
||||||
error(parser, parser->previous, "Expression statements not yet implemented");
|
expression(parser, nodeHandle);
|
||||||
|
consume(parser, TOKEN_SEMICOLON, "Expected ';' at the end of expression statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void statement(Parser* parser, Node* node) {
|
static void statement(Parser* parser, Node** nodeHandle) {
|
||||||
//block
|
//block
|
||||||
if (match(parser, TOKEN_BRACE_LEFT)) {
|
if (match(parser, TOKEN_BRACE_LEFT)) {
|
||||||
blockStmt(parser, node);
|
blockStmt(parser, nodeHandle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//print
|
//print
|
||||||
if (match(parser, TOKEN_PRINT)) {
|
if (match(parser, TOKEN_PRINT)) {
|
||||||
printStmt(parser, node);
|
printStmt(parser, nodeHandle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
if (match(parser, TOKEN_ASSERT)) {
|
if (match(parser, TOKEN_ASSERT)) {
|
||||||
assertStmt(parser, node);
|
assertStmt(parser, nodeHandle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//default
|
//default
|
||||||
expressionStmt(parser, node);
|
expressionStmt(parser, nodeHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
//declarations and definitions
|
//declarations and definitions
|
||||||
@@ -840,7 +857,7 @@ static void declaration(Parser* parser, Node** nodeHandle) { //assume nodeHandle
|
|||||||
varDecl(parser, nodeHandle);
|
varDecl(parser, nodeHandle);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
statement(parser, *nodeHandle);
|
statement(parser, nodeHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ unsigned char* compileString(char* source, size_t* size) {
|
|||||||
while(node != NULL) {
|
while(node != NULL) {
|
||||||
//pack up and leave
|
//pack up and leave
|
||||||
if (node->type == NODE_ERROR) {
|
if (node->type == NODE_ERROR) {
|
||||||
|
printf(ERROR "error node detected\n" RESET);
|
||||||
freeNode(node);
|
freeNode(node);
|
||||||
freeCompiler(&compiler);
|
freeCompiler(&compiler);
|
||||||
freeParser(&parser);
|
freeParser(&parser);
|
||||||
@@ -163,6 +164,7 @@ void repl() {
|
|||||||
while(node != NULL) {
|
while(node != NULL) {
|
||||||
//pack up and restart
|
//pack up and restart
|
||||||
if (node->type == NODE_ERROR) {
|
if (node->type == NODE_ERROR) {
|
||||||
|
printf(ERROR "error node detected\n" RESET);
|
||||||
error = true;
|
error = true;
|
||||||
freeNode(node);
|
freeNode(node);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ typedef enum TokenType {
|
|||||||
TOKEN_MODULO_ASSIGN,
|
TOKEN_MODULO_ASSIGN,
|
||||||
TOKEN_PLUS_PLUS,
|
TOKEN_PLUS_PLUS,
|
||||||
TOKEN_MINUS_MINUS,
|
TOKEN_MINUS_MINUS,
|
||||||
|
TOKEN_ASSIGN,
|
||||||
|
|
||||||
//logical operators
|
//logical operators
|
||||||
TOKEN_PAREN_LEFT,
|
TOKEN_PAREN_LEFT,
|
||||||
@@ -74,7 +75,6 @@ typedef enum TokenType {
|
|||||||
TOKEN_OR,
|
TOKEN_OR,
|
||||||
|
|
||||||
//other operators
|
//other operators
|
||||||
TOKEN_ASSIGN,
|
|
||||||
TOKEN_COLON,
|
TOKEN_COLON,
|
||||||
TOKEN_SEMICOLON,
|
TOKEN_SEMICOLON,
|
||||||
TOKEN_COMMA,
|
TOKEN_COMMA,
|
||||||
|
|||||||
Reference in New Issue
Block a user