1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-25 13:29:41 +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_ulong [] = { T_ULONG, 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)
/* 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.
*/
{
if ((T & Mask) == Mask) {
fprintf (F, "%s ", Name);
fprintf (F, "%s ", Name);
T &= ~Mask;
}
return T;
@ -361,7 +383,7 @@ unsigned SizeOf (const type* T)
case T_VOID:
Error (ERR_ILLEGAL_SIZE);
return 0;
return 1; /* Return something that makes sense */
case T_SCHAR:
case T_UCHAR:

View File

@ -147,6 +147,7 @@ extern type type_uint [];
extern type type_long [];
extern type type_ulong [];
extern type type_void [];
extern type type_size_t [];
@ -185,6 +186,11 @@ type* GetCharArrayType (unsigned Len);
type* GetImplicitFuncType (void);
/* 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);
/* Output translation of type array. */

View File

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

View File

@ -81,10 +81,14 @@ typedef enum {
NT_STRUCT_ACCESS, /* Access of a struct field */
NT_STRUCTPTR_ACCESS, /* Access via struct ptr */
NT_FUNCTION_CALL, /* Call a function */
NT_TYPECAST, /* A cast */
NT_ADDRESS, /* Address operator (&) */
NT_INDIRECT, /* Indirection operator (*) */
NT_UNARY_MINUS,
NT_COMPLEMENT, /* ~ */
NT_BOOL_NOT, /* ! */
NT_NOT, /* ~ */
NT_PLUS, /* + */
NT_MINUS, /* - */
NT_MUL, /* * */
@ -111,7 +115,6 @@ typedef enum {
NT_PRE_INC, /* ++ */
NT_POST_INC, /* ++ */
NT_BOOL_NOT, /* ! */
NT_BOOL_OR, /* || */
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)
{
/* Get the lower level expression */
@ -632,9 +667,8 @@ static ExprNode* PostfixExpr (void)
break;
case TOK_INC:
break;
case TOK_DEC:
Root = DoPostIncDec (Root);
break;
default:
@ -717,12 +751,26 @@ static ExprNode* DoUnaryPlusMinus (void)
/* In case of PLUS, we must do nothing */
if (Tok == TOK_PLUS) {
/* Use the operand unchanged */
Root = Op;
/* Return the operand unchanged */
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 {
/* Setup the expression tree */
/* Non constant value, setup the expression tree */
Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
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)
{
/* */
if (curtok == TOK_INC || curtok == TOK_DEC ||
curtok == TOK_PLUS || curtok == TOK_MINUS ||
curtok == TOK_AND || curtok == TOK_STAR ||
curtok == TOK_COMP || curtok == TOK_BOOL_NOT ||
curtok == TOK_AND || curtok == TOK_STAR ||
curtok == TOK_SIZEOF || IsTypeExpr ()) {
/* Check the token */
@ -754,23 +1031,24 @@ static ExprNode* UnaryExpr (void)
case TOK_MINUS:
return DoUnaryPlusMinus ();
case TOK_AND:
break;
case TOK_STAR:
break;
case TOK_COMP:
break;
return DoComplement ();
case TOK_BOOL_NOT:
break;
return DoBoolNot ();
case TOK_AND:
return DoAddress ();
case TOK_STAR:
return DoIndirect ();
case TOK_SIZEOF:
break;
return DoSizeOf ();
default:
break;
/* Type cast */
return DoTypeCast ();
}