1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-13 08:25:28 +00:00

Working on the new parser

git-svn-id: svn://svn.cc65.org/cc65/trunk@291 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2000-08-20 09:25:47 +00:00
parent 7e59a882c5
commit 64dac7e7b7
5 changed files with 331 additions and 22 deletions

View File

@@ -51,7 +51,7 @@
/*****************************************************************************/ /*****************************************************************************/
/* Data */ /* Data */
/*****************************************************************************/ /*****************************************************************************/
@@ -63,6 +63,7 @@ type type_uint [] = { T_UINT, T_END };
type type_long [] = { T_LONG, T_END }; type type_long [] = { T_LONG, T_END };
type type_ulong [] = { T_ULONG, T_END }; type type_ulong [] = { T_ULONG, T_END };
type type_void [] = { T_VOID, T_END }; type type_void [] = { T_VOID, T_END };
type type_size_t [] = { T_UINT, T_END };
@@ -190,13 +191,34 @@ type* GetImplicitFuncType (void)
type* PointerTo (const type* T)
/* Return a type string that is "pointer to T". The type string is allocated
* on the heap and may be freed after use.
*/
{
/* Get the size of the type string including the terminator */
unsigned Size = TypeLen (T) + 1;
/* Allocate the new type string */
type* P = TypeAlloc (Size + 1);
/* Create the return type... */
P[0] = T_PTR;
memcpy (P+1, T, Size * sizeof (type));
/* ...and return it */
return P;
}
static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name) static type PrintTypeComp (FILE* F, type T, type Mask, const char* Name)
/* Check for a specific component of the type. If it is there, print the /* Check for a specific component of the type. If it is there, print the
* name and remove it. Return the type with the component removed. * name and remove it. Return the type with the component removed.
*/ */
{ {
if ((T & Mask) == Mask) { if ((T & Mask) == Mask) {
fprintf (F, "%s ", Name); fprintf (F, "%s ", Name);
T &= ~Mask; T &= ~Mask;
} }
return T; return T;
@@ -361,7 +383,7 @@ unsigned SizeOf (const type* T)
case T_VOID: case T_VOID:
Error (ERR_ILLEGAL_SIZE); Error (ERR_ILLEGAL_SIZE);
return 0; return 1; /* Return something that makes sense */
case T_SCHAR: case T_SCHAR:
case T_UCHAR: case T_UCHAR:

View File

@@ -147,6 +147,7 @@ extern type type_uint [];
extern type type_long []; extern type type_long [];
extern type type_ulong []; extern type type_ulong [];
extern type type_void []; extern type type_void [];
extern type type_size_t [];
@@ -185,6 +186,11 @@ type* GetCharArrayType (unsigned Len);
type* GetImplicitFuncType (void); type* GetImplicitFuncType (void);
/* Return a type string for an inplicitly declared function */ /* Return a type string for an inplicitly declared function */
type* PointerTo (const type* T);
/* Return a type string that is "pointer to T". The type string is allocated
* on the heap and may be freed after use.
*/
void PrintType (FILE* F, const type* Type); void PrintType (FILE* F, const type* Type);
/* Output translation of type array. */ /* Output translation of type array. */

View File

@@ -121,7 +121,7 @@ static char* ErrMsg [ERR_COUNT-1] = {
"Too many initializers", "Too many initializers",
"Cannot initialize incomplete type", "Cannot initialize incomplete type",
"Cannot subscript", "Cannot subscript",
"Operation not allowed on these types", "Operation not allowed with this type of argument",
"Struct expected", "Struct expected",
"Struct/union has no field named `%s'", "Struct/union has no field named `%s'",
"Struct pointer expected", "Struct pointer expected",

View File

@@ -81,10 +81,14 @@ typedef enum {
NT_STRUCT_ACCESS, /* Access of a struct field */ NT_STRUCT_ACCESS, /* Access of a struct field */
NT_STRUCTPTR_ACCESS, /* Access via struct ptr */ NT_STRUCTPTR_ACCESS, /* Access via struct ptr */
NT_FUNCTION_CALL, /* Call a function */ NT_FUNCTION_CALL, /* Call a function */
NT_TYPECAST, /* A cast */
NT_ADDRESS, /* Address operator (&) */
NT_INDIRECT, /* Indirection operator (*) */
NT_UNARY_MINUS, NT_UNARY_MINUS,
NT_COMPLEMENT, /* ~ */
NT_BOOL_NOT, /* ! */
NT_NOT, /* ~ */
NT_PLUS, /* + */ NT_PLUS, /* + */
NT_MINUS, /* - */ NT_MINUS, /* - */
NT_MUL, /* * */ NT_MUL, /* * */
@@ -111,7 +115,6 @@ typedef enum {
NT_PRE_INC, /* ++ */ NT_PRE_INC, /* ++ */
NT_POST_INC, /* ++ */ NT_POST_INC, /* ++ */
NT_BOOL_NOT, /* ! */
NT_BOOL_OR, /* || */ NT_BOOL_OR, /* || */
NT_BOOL_AND, /* && */ NT_BOOL_AND, /* && */

View File

@@ -605,6 +605,41 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
static ExprNode* DoPostIncDec (ExprNode* Left)
/* Handle postincrement and postdecrement */
{
ExprNode* Root;
/* Determine the type of the node */
nodetype_t NT = (curtok == TOK_INC)? NT_POST_INC : NT_POST_DEC;
/* Skip the operator token */
NextToken ();
/* The operand must be an lvalue */
if (Left->LValue == 0) {
/* Print a diagnostics */
Error (ERR_LVALUE_EXPECTED);
/* It is safe to return the operand expression and probably better
* than returning an int, since the operand expression already has
* the correct type as expected by the program at this place, and
* it is even an rvalue.
*/
return Left;
}
/* Setup the expression tree */
Root = AllocExprNode (NT, Left->Type, RVALUE);
SetLeftNode (Root, Left);
/* Return the new node */
return Root;
}
static ExprNode* PostfixExpr (void) static ExprNode* PostfixExpr (void)
{ {
/* Get the lower level expression */ /* Get the lower level expression */
@@ -632,9 +667,8 @@ static ExprNode* PostfixExpr (void)
break; break;
case TOK_INC: case TOK_INC:
break;
case TOK_DEC: case TOK_DEC:
Root = DoPostIncDec (Root);
break; break;
default: default:
@@ -717,12 +751,26 @@ static ExprNode* DoUnaryPlusMinus (void)
/* In case of PLUS, we must do nothing */ /* In case of PLUS, we must do nothing */
if (Tok == TOK_PLUS) { if (Tok == TOK_PLUS) {
/* Use the operand unchanged */ /* Return the operand unchanged */
Root = Op; return Op;
} else if (Op->NT == NT_CONST) {
/* The value is constant, change it according to the insn */
if (IsClassInt (Op->Type)) {
/* Integer */
Op->V.I = -Op->V.I;
} else {
/* Float */
Op->V.F = -Op->V.F;
}
/* Return the operand itself */
return Op;
} else { } else {
/* Setup the expression tree */ /* Non constant value, setup the expression tree */
Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE); Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
SetLeftNode (Root, Op); SetLeftNode (Root, Op);
@@ -734,13 +782,242 @@ static ExprNode* DoUnaryPlusMinus (void)
static ExprNode* DoComplement (void)
/* Handle ~ */
{
ExprNode* Op;
ExprNode* Root;
/* Skip the operator token */
NextToken ();
/* Get the operand */
Op = UnaryExpr ();
/* Type check */
if (!IsClassInt (Op->Type)) {
/* Display diagnostic */
Error (ERR_OP_NOT_ALLOWED);
/* Free the errorneous node */
FreeExprNode (Op);
/* Return something that makes sense later */
return GetIntNode (0);
}
/* If the operand is constant, handle the operation directly */
if (Op->NT == NT_CONST) {
/* Change the value and return the operand node */
Op->V.I = ~Op->V.I;
return Op;
} else {
/* Setup the expression tree and return the new node */
Root = AllocExprNode (NT_COMPLEMENT, Op->Type, RVALUE);
SetLeftNode (Root, Op);
return Root;
}
}
static ExprNode* DoBoolNot (void)
/* Handle ! */
{
ExprNode* Op;
ExprNode* Root;
/* Skip the operator token */
NextToken ();
/* Get the operand */
Op = UnaryExpr ();
/* The boolean NOT operator eats anything - no need for a type check. */
/* Setup the expression tree and return the new node */
Root = AllocExprNode (NT_BOOL_NOT, type_int, RVALUE);
SetLeftNode (Root, Op);
return Root;
}
static ExprNode* DoAddress (void)
/* Handle the address operator & */
{
ExprNode* Op;
/* Skip the operator */
NextToken ();
/* Get the operand */
Op = UnaryExpr ();
/* Accept using the address operator with arrays. This is harmless, it
* will just be as using the array without the operator.
*/
if (IsTypeArray (Op->Type)) {
return Op;
}
/* We cannot operate on rvalues */
if (Op->LValue == 0) {
ExprNode* Root;
/* Print diagnostics */
Error (ERR_ILLEGAL_ADDRESS);
/* Free the problematic node */
FreeExprNode (Op);
/* Return something that is safe later */
Root = AllocExprNode (NT_CONST, PointerTo (type_void), 0);
Root->V.I = 0;
return Root;
}
/* Create the operator node and return it */
return AllocExprNode (NT_ADDRESS, PointerTo (Op->Type), RVALUE);
}
static ExprNode* DoIndirect (void)
/* Handle the indirection operaror * */
{
ExprNode* Op;
type* ResultType;
int LVal;
/* Skip the operator */
NextToken ();
/* Get the operand */
Op = UnaryExpr ();
/* Type check */
if (!IsClassPtr (Op->Type)) {
/* Print diagnostics */
Error (ERR_ILLEGAL_INDIRECT);
/* Free the problematic node */
FreeExprNode (Op);
/* Return something that is safe later ### */
return GetIntNode (0);
}
/* Get the type of the result */
ResultType = Indirect (Op->Type);
/* The result is an lvalue if it is not an array */
LVal = IsTypeArray (ResultType)? RVALUE : LVALUE;
/* Create the operator node and return it */
return AllocExprNode (NT_INDIRECT, ResultType, LVal);
}
static ExprNode* DoSizeOf (void)
/* Handle the sizeof operator */
{
ExprNode* N;
unsigned long Size;
/* Skip the left paren */
NextToken ();
/* A type or an actual variable access may follow */
if (IsTypeExpr ()) {
type Type[MAXTYPELEN];
/* A type in parenthesis. Skip the left paren. */
NextToken ();
/* Read the type and calculate the size. */
Size = SizeOf (ParseType (Type));
/* Closing paren must follow */
ConsumeRParen ();
} else {
/* Some other entity */
N = UnaryExpr ();
/* Get the size */
Size = SizeOf (N->Type);
/* Free the node */
FreeExprNode (N);
}
/* Create a constant node with type size_t and return it */
N = AllocExprNode (NT_CONST, type_size_t, RVALUE);
N->V.I = Size;
return N;
}
static ExprNode* DoTypeCast (void)
/* Handle type casts */
{
type TargetType[MAXTYPELEN];
ExprNode* Op;
ExprNode* Root;
/* Skip the left paren */
NextToken ();
/* Read the type */
ParseType (TargetType);
/* Closing paren */
ConsumeRParen ();
/* Read the expression we have to cast */
Op = UnaryExpr ();
/* As a minor optimization, check if the type is already correct. If so,
* do nothing.
*/
if (TypeCmp (TargetType, Op->Type) >= TC_EQUAL) {
/* Just return the operand as is */
return Op;
} else {
/* Must be casted. Setup the expression tree and return the new node */
Root = AllocExprNode (NT_BOOL_NOT, TargetType, RVALUE);
SetLeftNode (Root, Op);
return Root;
}
}
static ExprNode* UnaryExpr (void) static ExprNode* UnaryExpr (void)
{ {
/* */ /* */
if (curtok == TOK_INC || curtok == TOK_DEC || if (curtok == TOK_INC || curtok == TOK_DEC ||
curtok == TOK_PLUS || curtok == TOK_MINUS || curtok == TOK_PLUS || curtok == TOK_MINUS ||
curtok == TOK_AND || curtok == TOK_STAR ||
curtok == TOK_COMP || curtok == TOK_BOOL_NOT || curtok == TOK_COMP || curtok == TOK_BOOL_NOT ||
curtok == TOK_AND || curtok == TOK_STAR ||
curtok == TOK_SIZEOF || IsTypeExpr ()) { curtok == TOK_SIZEOF || IsTypeExpr ()) {
/* Check the token */ /* Check the token */
@@ -754,23 +1031,24 @@ static ExprNode* UnaryExpr (void)
case TOK_MINUS: case TOK_MINUS:
return DoUnaryPlusMinus (); return DoUnaryPlusMinus ();
case TOK_AND:
break;
case TOK_STAR:
break;
case TOK_COMP: case TOK_COMP:
break; return DoComplement ();
case TOK_BOOL_NOT: case TOK_BOOL_NOT:
break; return DoBoolNot ();
case TOK_AND:
return DoAddress ();
case TOK_STAR:
return DoIndirect ();
case TOK_SIZEOF: case TOK_SIZEOF:
break; return DoSizeOf ();
default: default:
break; /* Type cast */
return DoTypeCast ();
} }