mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 15:29:46 +00:00
Working on the new parser.
git-svn-id: svn://svn.cc65.org/cc65/trunk@368 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
669d063e75
commit
5cf9e0af18
@ -163,7 +163,7 @@ ExprHeap* PopExprHeap (void)
|
||||
|
||||
ExprNode* AllocExprNode (nodetype_t NT, type* Type, int LValue)
|
||||
/* Get a new node from the current expression heap */
|
||||
{
|
||||
{
|
||||
ExprNode* N;
|
||||
|
||||
/* Must have a heap */
|
||||
@ -205,4 +205,23 @@ void FreeExprNode (ExprNode* N)
|
||||
|
||||
|
||||
|
||||
void FreeExprTree (ExprNode* N)
|
||||
/* Free a complete expression tree starting with the current node */
|
||||
{
|
||||
if (IsBranchNode (N)) {
|
||||
/* Free the leaf nodes if necessary */
|
||||
if ((N->NT & NT_MASK_LIST) == NT_LIST_EXPR) {
|
||||
unsigned I;
|
||||
unsigned Count = CollCount (&N->List);
|
||||
for (I = 0; I < Count; ++I) {
|
||||
FreeExprNode (CollAt (&N->List, I));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the node itself */
|
||||
FreeExprNode (N);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -73,6 +73,9 @@ ExprNode* AllocExprNode (nodetype_t NT, type* Type, int LValue);
|
||||
void FreeExprNode (ExprNode* N);
|
||||
/* Free an expression node from the current expression heap */
|
||||
|
||||
void FreeExprTree (ExprNode* N);
|
||||
/* Free a complete expression tree starting with the current node */
|
||||
|
||||
|
||||
|
||||
/* End of exprheap.h */
|
||||
|
@ -33,6 +33,11 @@
|
||||
|
||||
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "error.h"
|
||||
#include "exprnode.h"
|
||||
|
||||
|
||||
@ -156,4 +161,321 @@ void SetNodeSym (ExprNode* N, struct SymEntry* Sym)
|
||||
|
||||
|
||||
|
||||
int IsLeafNode (const ExprNode* E)
|
||||
/* Return true if this is a leaf node */
|
||||
{
|
||||
return (E->NT & NT_MASK_LEAF) == NT_LEAF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int IsBranchNode (const ExprNode* E)
|
||||
/* Return true if this is a branch node */
|
||||
{
|
||||
return (E->NT & NT_MASK_LEAF) == NT_BRANCH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DumpExpr (FILE* F, const ExprNode* E)
|
||||
/* Dump an expression in UPN notation to the given file */
|
||||
{
|
||||
if (IsLeafNode (E)) {
|
||||
|
||||
/* Operand */
|
||||
switch (E->NT) {
|
||||
|
||||
case NT_SYM:
|
||||
/* Symbol */
|
||||
fprintf (F, "SYM ");
|
||||
break;
|
||||
|
||||
case NT_CONST:
|
||||
/* A constant of some sort */
|
||||
if (IsClassInt (E->Type)) {
|
||||
fprintf (F, "%0*lX ", SizeOf (E->Type), E->IVal);
|
||||
} else if (IsClassFloat (E->Type)) {
|
||||
fprintf (F, "%f ", E->FVal);
|
||||
} else {
|
||||
Internal ("Unknown type for NT_CONST");
|
||||
}
|
||||
break;
|
||||
|
||||
case NT_ASM:
|
||||
/* Inline assembler */
|
||||
fprintf (F, "ASM ");
|
||||
break;
|
||||
|
||||
case NT_REG_A:
|
||||
/* A register */
|
||||
fprintf (F, "REG_A ");
|
||||
break;
|
||||
|
||||
case NT_REG_X:
|
||||
/* X register */
|
||||
fprintf (F, "REG_X ");
|
||||
break;
|
||||
|
||||
case NT_REG_Y:
|
||||
/* Y register */
|
||||
fprintf (F, "REG_Y ");
|
||||
break;
|
||||
|
||||
case NT_REG_AX:
|
||||
/* AX register */
|
||||
fprintf (F, "REG_AX ");
|
||||
break;
|
||||
|
||||
case NT_REG_EAX:
|
||||
/* EAX register */
|
||||
fprintf (F, "REG_EAX ");
|
||||
break;
|
||||
|
||||
default:
|
||||
Internal ("Unknown node type: %04X", E->NT);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
unsigned I, Count;
|
||||
|
||||
/* Dump the operands */
|
||||
switch (E->NT & NT_MASK_LIST) {
|
||||
|
||||
case NT_LIST_EXPR:
|
||||
Count = CollCount (&E->List);
|
||||
for (I = 0; I < Count; ++I) {
|
||||
DumpExpr (F, CollConstAt (&E->List, I));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Internal ("Operator with LIST != NT_LIST_EXPR");
|
||||
|
||||
}
|
||||
|
||||
/* Dump the operator */
|
||||
switch (E->NT) {
|
||||
|
||||
case NT_ARRAY_SUBSCRIPT:
|
||||
/* Array subscript */
|
||||
fprintf (F, "[] ");
|
||||
break;
|
||||
|
||||
case NT_STRUCT_ACCESS:
|
||||
/* Access of a struct field */
|
||||
fprintf (F, ". ");
|
||||
break;
|
||||
|
||||
case NT_STRUCTPTR_ACCESS:
|
||||
/* Access via struct ptr */
|
||||
fprintf (F, "-> ");
|
||||
break;
|
||||
|
||||
case NT_FUNCTION_CALL:
|
||||
/* Call a function */
|
||||
fprintf (F, "CALL ");
|
||||
break;
|
||||
|
||||
case NT_TYPECAST:
|
||||
/* A cast */
|
||||
fprintf (F, "CAST ");
|
||||
break;
|
||||
|
||||
case NT_ADDRESS:
|
||||
/* Address operator (&) */
|
||||
fprintf (F, "ADDR ");
|
||||
break;
|
||||
|
||||
case NT_INDIRECT:
|
||||
/* Indirection operator (*) */
|
||||
fprintf (F, "FETCH ");
|
||||
break;
|
||||
|
||||
case NT_UNARY_MINUS:
|
||||
/* - */
|
||||
fprintf (F, "NEG ");
|
||||
break;
|
||||
|
||||
case NT_COMPLEMENT:
|
||||
/* ~ */
|
||||
fprintf (F, "~ ");
|
||||
break;
|
||||
|
||||
case NT_BOOL_NOT:
|
||||
/* ! */
|
||||
fprintf (F, "! ");
|
||||
break;
|
||||
|
||||
case NT_PLUS:
|
||||
/* + */
|
||||
fprintf (F, "+ ");
|
||||
break;
|
||||
|
||||
case NT_MINUS:
|
||||
/* - */
|
||||
fprintf (F, "- ");
|
||||
break;
|
||||
|
||||
case NT_MUL:
|
||||
/* * */
|
||||
fprintf (F, "* ");
|
||||
break;
|
||||
|
||||
case NT_DIV:
|
||||
/* / */
|
||||
fprintf (F, "/ ");
|
||||
break;
|
||||
|
||||
case NT_SHL:
|
||||
/* << */
|
||||
fprintf (F, "<< ");
|
||||
break;
|
||||
|
||||
case NT_SHR:
|
||||
/* >> */
|
||||
fprintf (F, ">> ");
|
||||
break;
|
||||
|
||||
case NT_AND:
|
||||
/* & */
|
||||
fprintf (F, "& ");
|
||||
break;
|
||||
|
||||
case NT_OR:
|
||||
/* | */
|
||||
fprintf (F, "| ");
|
||||
break;
|
||||
|
||||
case NT_XOR:
|
||||
/* ^ */
|
||||
fprintf (F, "^ ");
|
||||
break;
|
||||
|
||||
case NT_TERNARY:
|
||||
/* ?: */
|
||||
fprintf (F, "?: ");
|
||||
break;
|
||||
|
||||
case NT_ASSIGN:
|
||||
/* = */
|
||||
fprintf (F, "= ");
|
||||
break;
|
||||
|
||||
case NT_PLUS_ASSIGN:
|
||||
/* += */
|
||||
fprintf (F, "+= ");
|
||||
break;
|
||||
|
||||
case NT_MINUS_ASSIGN:
|
||||
/* -= */
|
||||
fprintf (F, "-= ");
|
||||
break;
|
||||
|
||||
case NT_MUL_ASSIGN:
|
||||
/* *= */
|
||||
fprintf (F, "*= ");
|
||||
break;
|
||||
|
||||
case NT_DIV_ASSIGN:
|
||||
/* /= */
|
||||
fprintf (F, "/= ");
|
||||
break;
|
||||
|
||||
case NT_SHL_ASSIGN:
|
||||
/* <<= */
|
||||
fprintf (F, "<<= ");
|
||||
break;
|
||||
|
||||
case NT_SHR_ASSIGN:
|
||||
/* >>= */
|
||||
fprintf (F, ">>= ");
|
||||
break;
|
||||
|
||||
case NT_AND_ASSIGN:
|
||||
/* &= */
|
||||
fprintf (F, "&= ");
|
||||
break;
|
||||
|
||||
case NT_OR_ASSIGN:
|
||||
/* |= */
|
||||
fprintf (F, "|= ");
|
||||
break;
|
||||
|
||||
case NT_XOR_ASSIGN:
|
||||
/* ^= */
|
||||
fprintf (F, "^= ");
|
||||
break;
|
||||
|
||||
case NT_PRE_DEC:
|
||||
/* -- */
|
||||
fprintf (F, "<-- ");
|
||||
break;
|
||||
|
||||
case NT_POST_DEC:
|
||||
/* -- */
|
||||
fprintf (F, "--> ");
|
||||
break;
|
||||
|
||||
case NT_PRE_INC:
|
||||
/* ++ */
|
||||
fprintf (F, "<++ ");
|
||||
break;
|
||||
|
||||
case NT_POST_INC:
|
||||
/* ++ */
|
||||
fprintf (F, "++> ");
|
||||
break;
|
||||
|
||||
case NT_BOOL_OR:
|
||||
/* || */
|
||||
fprintf (F, "|| ");
|
||||
break;
|
||||
|
||||
case NT_BOOL_AND:
|
||||
/* && */
|
||||
fprintf (F, "&& ");
|
||||
break;
|
||||
|
||||
case NT_EQ:
|
||||
/* == */
|
||||
fprintf (F, "== ");
|
||||
break;
|
||||
|
||||
case NT_NE:
|
||||
/* != */
|
||||
fprintf (F, "!= ");
|
||||
break;
|
||||
|
||||
case NT_LT:
|
||||
/* < */
|
||||
fprintf (F, "< ");
|
||||
break;
|
||||
|
||||
case NT_LE:
|
||||
/* <= */
|
||||
fprintf (F, "<= ");
|
||||
break;
|
||||
|
||||
case NT_GT:
|
||||
/* > */
|
||||
fprintf (F, "> ");
|
||||
break;
|
||||
|
||||
case NT_GE:
|
||||
/* >= */
|
||||
fprintf (F, ">= ");
|
||||
break;
|
||||
|
||||
default:
|
||||
Internal ("Unknown node type: %04X", E->NT);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -76,8 +76,9 @@ typedef enum {
|
||||
NT_MASK_LIST = 0x0300,
|
||||
|
||||
/* Two bits telling if this is a leaf or a branch */
|
||||
NT_BRANCH = 0x4000, /* Branch */
|
||||
NT_LEAF = 0x8000, /* Leaf */
|
||||
NT_LEAF = 0x0000, /* Leaf */
|
||||
NT_BRANCH = 0x8000, /* Branch */
|
||||
NT_MASK_LEAF = 0x8000,
|
||||
|
||||
/* Special node type */
|
||||
NT_NONE = 0x0000, /* None (invalid) op */
|
||||
@ -142,7 +143,9 @@ typedef enum {
|
||||
NT_LT = 0x0037 | NT_BRANCH | NT_LIST_EXPR, /* < */
|
||||
NT_LE = 0x0038 | NT_BRANCH | NT_LIST_EXPR, /* <= */
|
||||
NT_GT = 0x0039 | NT_BRANCH | NT_LIST_EXPR, /* > */
|
||||
NT_GE = 0x003A | NT_BRANCH | NT_LIST_EXPR /* >= */
|
||||
NT_GE = 0x003A | NT_BRANCH | NT_LIST_EXPR, /* >= */
|
||||
|
||||
NT_MASK_TYPE = 0x00FF
|
||||
|
||||
} nodetype_t;
|
||||
|
||||
@ -224,6 +227,12 @@ struct SymEntry* GetNodeSym (ExprNode* N);
|
||||
void SetNodeSym (ExprNode* N, struct SymEntry* Sym);
|
||||
/* Set the symbol entry in a NT_SYM node */
|
||||
|
||||
int IsLeafNode (const ExprNode* E);
|
||||
/* Return true if this is a leaf node */
|
||||
|
||||
int IsBranchNode (const ExprNode* E);
|
||||
/* Return true if this is a branch node */
|
||||
|
||||
|
||||
|
||||
/* End of exprnode.h */
|
||||
@ -232,5 +241,3 @@ void SetNodeSym (ExprNode* N, struct SymEntry* Sym);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -543,8 +543,8 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
|
||||
/* Call to non function */
|
||||
Error (ERR_ILLEGAL_FUNC_CALL);
|
||||
|
||||
/* Free the old node */
|
||||
FreeExprNode (Left);
|
||||
/* Free the old tree */
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Return something safe */
|
||||
return GetIntNode (0);
|
||||
@ -759,11 +759,11 @@ static ExprNode* DoUnaryPlusMinus (void)
|
||||
/* Type check */
|
||||
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
|
||||
|
||||
/* Display diagnostic */
|
||||
/* Output diagnostic */
|
||||
Error (ERR_SYNTAX);
|
||||
|
||||
/* Free the errorneous node */
|
||||
FreeExprNode (Op);
|
||||
FreeExprTree (Op);
|
||||
|
||||
/* Return something that makes sense later */
|
||||
return GetIntNode (0);
|
||||
@ -822,7 +822,7 @@ static ExprNode* DoComplement (void)
|
||||
Error (ERR_OP_NOT_ALLOWED);
|
||||
|
||||
/* Free the errorneous node */
|
||||
FreeExprNode (Op);
|
||||
FreeExprTree (Op);
|
||||
|
||||
/* Return something that makes sense later */
|
||||
return GetIntNode (0);
|
||||
@ -894,8 +894,8 @@ static ExprNode* DoAddress (void)
|
||||
/* Print diagnostics */
|
||||
Error (ERR_ILLEGAL_ADDRESS);
|
||||
|
||||
/* Free the problematic node */
|
||||
FreeExprNode (Op);
|
||||
/* Free the problematic tree */
|
||||
FreeExprTree (Op);
|
||||
|
||||
/* Return something that is safe later */
|
||||
Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
|
||||
@ -928,8 +928,8 @@ static ExprNode* DoIndirect (void)
|
||||
/* Print diagnostics */
|
||||
Error (ERR_ILLEGAL_INDIRECT);
|
||||
|
||||
/* Free the problematic node */
|
||||
FreeExprNode (Op);
|
||||
/* Free the problematic tree */
|
||||
FreeExprTree (Op);
|
||||
|
||||
/* Return something that is safe later ### */
|
||||
return GetIntNode (0);
|
||||
@ -980,7 +980,7 @@ static ExprNode* DoSizeOf (void)
|
||||
Size = SizeOf (N->Type);
|
||||
|
||||
/* Free the node */
|
||||
FreeExprNode (N);
|
||||
FreeExprTree (N);
|
||||
|
||||
}
|
||||
|
||||
@ -1021,8 +1021,8 @@ static ExprNode* DoTypeCast (void)
|
||||
|
||||
} else {
|
||||
|
||||
/* Must be casted. Setup the expression tree and return the new node */
|
||||
Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
|
||||
/* Must be casted. Setup the expression tree and return the new node */
|
||||
Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
|
||||
SetLeftNode (Root, Op);
|
||||
return Root;
|
||||
|
||||
@ -1049,7 +1049,7 @@ static ExprNode* UnaryExpr (void)
|
||||
|
||||
case TOK_PLUS:
|
||||
case TOK_MINUS:
|
||||
return DoUnaryPlusMinus ();
|
||||
return DoUnaryPlusMinus ();
|
||||
|
||||
case TOK_COMP:
|
||||
return DoComplement ();
|
||||
@ -1066,22 +1066,61 @@ static ExprNode* UnaryExpr (void)
|
||||
case TOK_SIZEOF:
|
||||
return DoSizeOf ();
|
||||
|
||||
default:
|
||||
/* Type cast */
|
||||
return DoTypeCast ();
|
||||
default:
|
||||
/* Type cast */
|
||||
return DoTypeCast ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Call the lower level */
|
||||
return PostfixExpr ();
|
||||
/* Call the lower level */
|
||||
return PostfixExpr ();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ExprNode* DoMul (ExprNode* Left)
|
||||
/* Handle multiplication */
|
||||
{
|
||||
type TargetType[MAXTYPELEN];
|
||||
ExprNode* Right;
|
||||
ExprNode* Root;
|
||||
|
||||
/* Check the type of the left operand */
|
||||
if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
|
||||
MError ("Invalid left operand to binary operator `*'");
|
||||
FreeExprTree (Left);
|
||||
Left = GetIntNode (0);
|
||||
}
|
||||
|
||||
/* Skip the operator token */
|
||||
NextToken ();
|
||||
|
||||
/* Read the right expression */
|
||||
Right = UnaryExpr ();
|
||||
|
||||
/* Check the type of the right operand */
|
||||
if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
|
||||
MError ("Invalid right operand to binary operator `*'");
|
||||
FreeExprTree (Right);
|
||||
Right = GetIntNode (0);
|
||||
}
|
||||
|
||||
/* Do minor optimizations ### */
|
||||
|
||||
/* Make the root node */
|
||||
Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
|
||||
SetLeftNode (Root, Left);
|
||||
SetRightNode (Root, Right);
|
||||
|
||||
return Root;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ExprNode* MultExpr (void)
|
||||
/* Handle multiplicative expressions: '*' '/' and '%' */
|
||||
{
|
||||
@ -1094,6 +1133,7 @@ static ExprNode* MultExpr (void)
|
||||
switch (CurTok.Tok) {
|
||||
|
||||
case TOK_MUL:
|
||||
Root = DoMul (Root);
|
||||
break;
|
||||
|
||||
case TOK_DIV:
|
||||
@ -1262,8 +1302,8 @@ static ExprNode* AndExpr (void)
|
||||
Error (ERR_OP_NOT_ALLOWED);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create something safe */
|
||||
Root = GetIntNode (0);
|
||||
@ -1277,8 +1317,8 @@ static ExprNode* AndExpr (void)
|
||||
int Result = GetBoolRep (Left) & GetBoolRep (Right);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create a constant result */
|
||||
Root = GetIntNode (Result);
|
||||
@ -1325,8 +1365,8 @@ static ExprNode* XorExpr (void)
|
||||
Error (ERR_OP_NOT_ALLOWED);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create something safe */
|
||||
Root = GetIntNode (0);
|
||||
@ -1340,8 +1380,8 @@ static ExprNode* XorExpr (void)
|
||||
int Result = GetBoolRep (Left) ^ GetBoolRep (Right);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create a constant result */
|
||||
Root = GetIntNode (Result);
|
||||
@ -1388,8 +1428,8 @@ static ExprNode* OrExpr (void)
|
||||
Error (ERR_OP_NOT_ALLOWED);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create something safe */
|
||||
Root = GetIntNode (0);
|
||||
@ -1403,8 +1443,8 @@ static ExprNode* OrExpr (void)
|
||||
int Result = GetBoolRep (Left) | GetBoolRep (Right);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create a constant result */
|
||||
Root = GetIntNode (Result);
|
||||
@ -1451,8 +1491,8 @@ static ExprNode* BoolAndExpr (void)
|
||||
int Result = GetBoolRep (Left) && GetBoolRep (Right);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create a constant result */
|
||||
Root = GetIntNode (Result);
|
||||
@ -1499,8 +1539,8 @@ static ExprNode* BoolOrExpr (void)
|
||||
int Result = GetBoolRep (Left) && GetBoolRep (Right);
|
||||
|
||||
/* Remove the unneeded nodes */
|
||||
FreeExprNode (Right);
|
||||
FreeExprNode (Left);
|
||||
FreeExprTree (Right);
|
||||
FreeExprTree (Left);
|
||||
|
||||
/* Create a constant result */
|
||||
Root = GetIntNode (Result);
|
||||
|
Loading…
Reference in New Issue
Block a user