mirror of
https://github.com/cc65/cc65.git
synced 2025-01-10 19:29:45 +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:
parent
7e59a882c5
commit
64dac7e7b7
@ -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:
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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, /* && */
|
||||
|
||||
|
@ -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 ();
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user