1
0
mirror of https://github.com/cc65/cc65.git synced 2024-07-05 06:28:57 +00:00

Working on the new parser

git-svn-id: svn://svn.cc65.org/cc65/trunk@290 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2000-08-19 21:55:06 +00:00
parent 66b40d1a84
commit 7e59a882c5
12 changed files with 1385 additions and 56 deletions

View File

@ -511,6 +511,22 @@ int IsTypeLong (const type* T)
int IsTypeFloat (const type* T)
/* Return true if this is a float type */
{
return (T[0] & T_MASK_TYPE) == T_TYPE_FLOAT;
}
int IsTypeDouble (const type* T)
/* Return true if this is a double type */
{
return (T[0] & T_MASK_TYPE) == T_TYPE_DOUBLE;
}
int IsTypePtr (const type* T)
/* Return true if this is a pointer type */
{
@ -551,6 +567,14 @@ int IsClassInt (const type* T)
int IsClassFloat (const type* T)
/* Return true if this is a float type */
{
return (T[0] & T_MASK_CLASS) == T_CLASS_FLOAT;
}
int IsClassPtr (const type* T)
/* Return true if this is a pointer type */
{

View File

@ -40,6 +40,9 @@
#include <stdio.h>
/* common */
#include "attrib.h"
/*****************************************************************************/
@ -223,67 +226,76 @@ type* Indirect (type* Type);
* given type points to.
*/
int IsTypeChar (const type* T);
int IsTypeChar (const type* T) attribute ((const));
/* Return true if this is a character type */
int IsTypeInt (const type* T);
int IsTypeInt (const type* T) attribute ((const));
/* Return true if this is an int type (signed or unsigned) */
int IsTypeLong (const type* T);
int IsTypeLong (const type* T) attribute ((const));
/* Return true if this is a long type (signed or unsigned) */
int IsTypePtr (const type* Type);
int IsTypeFloat (const type* T) attribute ((const));
/* Return true if this is a float type */
int IsTypeDouble (const type* T) attribute ((const));
/* Return true if this is a double type */
int IsTypePtr (const type* Type) attribute ((const));
/* Return true if this is a pointer type */
int IsTypeArray (const type* Type);
int IsTypeArray (const type* Type) attribute ((const));
/* Return true if this is an array type */
int IsTypeVoid (const type* Type);
int IsTypeVoid (const type* Type) attribute ((const));
/* Return true if this is a void type */
int IsTypeFunc (const type* Type);
int IsTypeFunc (const type* Type) attribute ((const));
/* Return true if this is a function class */
int IsClassInt (const type* Type);
int IsClassInt (const type* Type) attribute ((const));
/* Return true if this is an integer type */
int IsClassPtr (const type* Type);
int IsClassFloat (const type* Type) attribute ((const));
/* Return true if this is a float type */
int IsClassPtr (const type* Type) attribute ((const));
/* Return true if this is a pointer type */
int IsClassStruct (const type* Type);
int IsClassStruct (const type* Type) attribute ((const));
/* Return true if this is a struct type */
int IsSignUnsigned (const type* Type);
int IsSignUnsigned (const type* Type) attribute ((const));
/* Return true if this is an unsigned type */
int IsQualConst (const type* T);
int IsQualConst (const type* T) attribute ((const));
/* Return true if the given type has a const memory image */
int IsQualVolatile (const type* T);
int IsQualVolatile (const type* T) attribute ((const));
/* Return true if the given type has a volatile type qualifier */
int IsFastCallFunc (const type* T);
int IsFastCallFunc (const type* T) attribute ((const));
/* Return true if this is a function type with __fastcall__ calling conventions */
int IsTypeFuncPtr (const type* T);
int IsTypeFuncPtr (const type* T) attribute ((const));
/* Return true if this is a function pointer */
type GetType (const type* T);
type GetType (const type* T) attribute ((const));
/* Get the raw type */
type GetClass (const type* T);
type GetClass (const type* T) attribute ((const));
/* Get the class of a type string */
type GetSignedness (const type* T);
type GetSignedness (const type* T) attribute ((const));
/* Get the sign of a type */
type GetSizeModifier (const type* T);
type GetSizeModifier (const type* T) attribute ((const));
/* Get the size modifier of a type */
type GetQualifier (const type* T);
type GetQualifier (const type* T) attribute ((const));
/* Get the qualifier from the given type string */
struct FuncDesc* GetFuncDesc (const type* T);
struct FuncDesc* GetFuncDesc (const type* T) attribute ((const));
/* Get the FuncDesc pointer from a function or pointer-to-function type */

View File

@ -37,6 +37,11 @@
#define ERROR_H
/* common */
#include "attrib.h"
/*****************************************************************************/
/* Data */
@ -197,7 +202,7 @@ void PPError (unsigned ErrNum, ...);
void Fatal (unsigned FatNum, ...);
/* Print a message about a fatal error and die */
void Internal (char* Format, ...);
void Internal (char* Format, ...) attribute ((noreturn));
/* Print a message about an internal compiler error and die. */
void ErrorReport (void);

208
src/cc65/exprheap.c Normal file
View File

@ -0,0 +1,208 @@
/*****************************************************************************/
/* */
/* exprheap.c */
/* */
/* Expression node heap manager */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
/* common */
#include "check.h"
#include "xmalloc.h"
/* cc65 */
#include "exprheap.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* A block of expression nodes */
typedef struct ExprNodeBlock ExprNodeBlock;
struct ExprNodeBlock {
ExprNodeBlock* Next; /* Pointer to next block */
unsigned Count; /* Number of nodes in the block */
unsigned Used; /* Number of nodes used */
ExprNode Nodes[1]; /* Nodes, dynamically allocated */
};
/* An expression heap */
struct ExprHeap {
ExprHeap* Last; /* Upper level expression tree */
ExprNodeBlock* BlockRoot; /* Root of node blocks */
ExprNodeBlock* BlockLast; /* Last node block */
ExprNode* FreeList; /* List of free nodes */
};
/* The current expression heap */
static ExprHeap* CurHeap = 0;
/*****************************************************************************/
/* struct ExprHeapBlock */
/*****************************************************************************/
static ExprNodeBlock* NewExprNodeBlock (unsigned Count)
/* Create a new ExprNodeBlock, initialize and return it */
{
/* Calculate the size of the memory block requested */
unsigned Size = sizeof (ExprNodeBlock) + (Count-1) * sizeof (ExprNode);
/* Allocate memory */
ExprNodeBlock* B = xmalloc (Size);
/* Initialize the fields */
B->Next = 0;
B->Count = Count;
B->Used = 0;
/* Return the new block */
return B;
}
/*****************************************************************************/
/* struct ExprHeap */
/*****************************************************************************/
static ExprHeap* NewExprHeap (void)
/* Create and return a new expression tree */
{
/* Allocate memory */
ExprHeap* H = xmalloc (sizeof (ExprHeap));
/* Allocate the first node block */
H->BlockRoot = NewExprNodeBlock (64);
/* Initialize the remaining fields */
H->Last = 0;
H->BlockLast = H->BlockRoot;
H->FreeList = 0;
/* Return the new heap */
return H;
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void PushExprHeap (void)
/* Create a new expression heap and push it onto the expression heap stack, so
* it is the current expression heap.
*/
{
/* Create a new heap */
ExprHeap* H = NewExprHeap ();
/* Push it onto the stack */
H->Last = CurHeap;
CurHeap = H;
}
ExprHeap* PopExprHeap (void)
/* Pop the current expression heap from the heap stack and return it */
{
ExprHeap* H;
/* Cannot pop a non existant heap */
PRECONDITION (CurHeap != 0);
/* Pop the heap */
H = CurHeap;
CurHeap = H->Last;
/* Return the old heap */
return H;
}
ExprNode* AllocExprNode (nodetype_t NT, type* Type, int LValue)
/* Get a new node from the current expression heap */
{
ExprNode* N;
/* Must have a heap */
PRECONDITION (CurHeap != 0);
/* Get a node from the freelist if possible */
if (CurHeap->FreeList) {
/* There are nodes in the free list */
N = CurHeap->FreeList;
CurHeap->FreeList = N->MData.Next;
} else {
/* Free list is empty, allocate a new node */
ExprNodeBlock* B = CurHeap->BlockLast;
if (B->Used >= B->Count) {
/* No nodes left, allocate a new node block */
B = NewExprNodeBlock (64);
CurHeap->BlockLast->Next = B;
CurHeap->BlockLast = B;
}
N = B->Nodes + B->Count++;
}
/* Initialize and return the allocated node */
return InitExprNode (N, NT, Type, LValue, CurHeap);
}
void FreeExprNode (ExprNode* N)
/* Free an expression node from the current expression heap */
{
/* There must be a heap, and the node must be from this heap */
PRECONDITION (CurHeap != 0 && N->MData.Owner == CurHeap);
/* Insert the node in the freelist invalidating the owner pointer */
N->MData.Next = CurHeap->FreeList;
CurHeap->FreeList = N;
}

83
src/cc65/exprheap.h Normal file
View File

@ -0,0 +1,83 @@
/*****************************************************************************/
/* */
/* exprheap.h */
/* */
/* Expression node heap manager */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef EXPRHEAP_H
#define EXPRHEAP_H
#include "exprnode.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* An expression heap */
typedef struct ExprHeap ExprHeap;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void PushExprHeap (void);
/* Create a new expression heap and push it onto the expression heap stack, so
* it is the current expression heap.
*/
ExprHeap* PopExprHeap (void);
/* Pop the current expression heap from the heap stack and return it */
ExprNode* AllocExprNode (nodetype_t NT, type* Type, int LValue);
/* Get a new node from the current expression heap */
void FreeExprNode (ExprNode* N);
/* Free an expression node from the current expression heap */
/* End of exprheap.h */
#endif

View File

@ -43,15 +43,115 @@
void InitExprNode (ExprNode* E)
ExprNode* InitExprNode (ExprNode* E, nodetype_t NT, type* Type,
int LValue, struct ExprHeap* Owner)
/* Initialize a new expression node */
{
E->Left = 0;
E->Right = 0;
E->NT = NT_NONE;
E->Type = 0;
E->LValue = 0;
/* Intialize basic data */
E->MData.Owner = Owner;
E->NT = NT;
E->Type = Type;
E->LValue = LValue;
/* Initialize the expression list in the node */
InitCollection (&E->List);
/* Return the node just initialized */
return E;
}
void* GetItem (ExprNode* N, unsigned Index)
/* Return one of the items from the nodes item list */
{
return CollAt (&N->List, Index);
}
void AppendItem (ExprNode* N, void* Item)
/* Append an item to the nodes item list */
{
CollAppend (&N->List, Item);
}
void SetItem (ExprNode* N, void* Item, unsigned Index)
/* Set a specific node item. The item list is filled with null pointers as
* needed.
*/
{
if (Index >= CollCount (&N->List)) {
/* Fill up with NULL pointers */
while (Index >= CollCount (&N->List) < Index) {
CollAppend (&N->List, 0);
}
/* Append the new item */
CollAppend (&N->List, Item);
} else {
/* There is an item with this index, replace it */
CollReplace (&N->List, Item, Index);
}
}
ExprNode* GetNode (ExprNode* N, unsigned Index)
/* Get one of the sub-nodes from the list */
{
return GetNode (N, Index);
}
ExprNode* GetLeftNode (ExprNode* N)
/* Get the left sub-node from the list */
{
return GetNode (N, IDX_LEFT);
}
void SetLeftNode (ExprNode* Root, ExprNode* Left)
/* Set the left node in Root */
{
SetItem (Root, Left, IDX_LEFT);
}
ExprNode* GetRightNode (ExprNode* N)
/* Get the right sub-node from the list */
{
return GetNode (N, IDX_RIGHT);
}
void SetRightNode (ExprNode* Root, ExprNode* Right)
/* Set the right node in Root */
{
SetItem (Root, Right, IDX_RIGHT);
}
struct SymEntry* GetNodeSym (ExprNode* N)
/* Get the symbol entry for a NT_SYM node */
{
return GetItem (N, IDX_SYM);
}
void SetNodeSym (ExprNode* N, struct SymEntry* Sym)
/* Set the symbol entry in a NT_SYM node */
{
SetItem (N, Sym, IDX_SYM);
}

View File

@ -38,16 +38,21 @@
/* common */
#include "coll.h"
/* cc65 */
#include "datatype.h"
/*****************************************************************************/
/* Forwards */
/* Forwards */
/*****************************************************************************/
struct ExprHeap;
struct SymEntry;
@ -64,9 +69,7 @@ typedef enum {
NT_SYM, /* Symbol */
NT_CONST, /* A constant of some sort */
NT_ICAST, /* Implicit type cast */
NT_ECAST, /* Explicit type cast */
NT_ASM, /* Inline assembler */
NT_REG_A, /* A register */
NT_REG_X, /* X register */
@ -74,9 +77,12 @@ typedef enum {
NT_REG_AX, /* AX register */
NT_REG_EAX, /* EAX register */
NT_CALLFUNC, /* Function call */
NT_PUSH, /* Push the value onto the stack */
NT_POP, /* Pop the value from the stack */
NT_ARRAY_SUBSCRIPT, /* Array subscript */
NT_STRUCT_ACCESS, /* Access of a struct field */
NT_STRUCTPTR_ACCESS, /* Access via struct ptr */
NT_FUNCTION_CALL, /* Call a function */
NT_UNARY_MINUS,
NT_NOT, /* ~ */
NT_PLUS, /* + */
@ -127,36 +133,79 @@ typedef enum {
typedef struct ExprNode ExprNode;
struct ExprNode {
ExprNode* Left; /* Left and right leaves */
ExprNode* Right;
/* Management data */
union {
struct ExprHeap* Owner; /* Heap, this node is in */
struct ExprNode* Next; /* Next in free list */
} MData;
Collection List; /* List of subexpressions */
nodetype_t NT; /* Node type */
type* Type; /* Resulting type */
int LValue; /* True if this is an lvalue */
type* Type; /* Resulting type */
int LValue; /* True if this is an lvalue */
union {
/* Branch data */
ExprNode* Test; /* Third expr for ternary op */
/* Leave data */
long I; /* Constant int value if any */
double F; /* Constant float value if any */
struct SymEntry* Sym; /* Symbol table entry if any */
} V;
};
/* Predefined indices for node items in List */
enum {
IDX_LEFT = 0,
IDX_RIGHT = 1,
IDX_SYM = 0
};
/* Some other constants for better readability */
enum {
RVALUE = 0,
LVALUE = 1
};
/*****************************************************************************/
/* Code */
/* Code */
/*****************************************************************************/
void InitExprNode (ExprNode* E);
ExprNode* InitExprNode (ExprNode* E, nodetype_t NT, type* Type,
int LValue, struct ExprHeap* Owner);
/* Initialize a new expression node */
void* GetItem (ExprNode* N, unsigned Index);
/* Return one of the items from the nodes item list */
void AppendItem (ExprNode* N, void* Item);
/* Append an item to the nodes item list */
void SetItem (ExprNode* N, void* Item, unsigned Index);
/* Set a specific node item. The item list is filled with null pointers as
* needed.
*/
ExprNode* GetLeftNode (ExprNode* N);
/* Get the left sub-node from the list */
void SetLeftNode (ExprNode* Root, ExprNode* Left);
/* Set the left node in Root */
ExprNode* GetRightNode (ExprNode* N);
/* Get the right sub-node from the list */
void SetRightNode (ExprNode* Root, ExprNode* Right);
/* Set the right node in Root */
struct SymEntry* GetNodeSym (ExprNode* N);
/* Get the symbol entry for a NT_SYM node */
void SetNodeSym (ExprNode* N, struct SymEntry* Sym);
/* Set the symbol entry in a NT_SYM node */
/* End of exprnode.h */

View File

@ -24,8 +24,8 @@ OBJS = anonname.o \
declare.o \
error.o \
expr.o \
exprheap.o \
exprnode.o \
exprtree.o \
funcdesc.o \
function.o \
global.o \
@ -70,7 +70,7 @@ cc65: $(OBJS)
clean:
rm -f *~ core *.map
zap: clean
rm -f *.o $(EXECS) .depend

View File

@ -73,14 +73,14 @@ OBJS = anonname.obj \
asmline.obj \
codegen.obj \
compile.obj \
cpu.obj \
cpu.obj \
ctrans.obj \
datatype.obj \
declare.obj \
error.obj \
expr.obj \
exprheap.obj \
exprnode.obj \
exprtree.obj \
funcdesc.obj \
function.obj \
global.obj \
@ -138,8 +138,8 @@ FILE datatype.obj
FILE declare.obj
FILE error.obj
FILE expr.obj
FILE exprheap.obj
FILE exprnode.obj
FILE exprtree.obj
FILE funcdesc.obj
FILE function.obj
FILE global.obj

783
src/cc65/parser.c Normal file
View File

@ -0,0 +1,783 @@
/*****************************************************************************/
/* */
/* parser.c */
/* */
/* Expression parser */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* common */
#include "check.h"
#include "xmalloc.h"
/* cc65 */
#include "datatype.h"
#include "declare.h"
#include "error.h"
#include "exprheap.h"
#include "funcdesc.h"
#include "function.h"
#include "global.h"
#include "litpool.h"
#include "macrotab.h"
#include "preproc.h"
#include "scanner.h"
#include "stdfunc.h"
#include "symtab.h"
#include "typecmp.h"
#include "parser.h"
/*****************************************************************************/
/* Forwards */
/*****************************************************************************/
static ExprNode* UnaryExpr (void);
ExprNode* Expr1 (void);
ExprNode* Expr0 (void);
/*****************************************************************************/
/* Helper functions */
/*****************************************************************************/
static int IsTypeExpr (void)
/* Return true if some sort of variable or type is waiting (helper for cast
* and sizeof() in hie10).
*/
{
SymEntry* Entry;
return curtok == TOK_LPAREN && (
(nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
(nxttok == TOK_CONST) ||
(nxttok == TOK_IDENT &&
(Entry = FindSym (NextTok.Ident)) != 0 &&
IsTypeDef (Entry))
);
}
/*****************************************************************************/
/* Expression node helper functions */
/*****************************************************************************/
static ExprNode* GetIntNode (int Value)
/* Allocate a new expression node from the tree, make it a valid integer
* node and return it. Often used if an error occurs to get a safe expression
* tree.
*/
{
ExprNode* N = AllocExprNode (NT_CONST, type_int, RVALUE);
N->V.I = Value;
return N;
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
ExprNode* DoAsm (void)
/* This function parses ASM statements. The syntax of the ASM directive
* looks like the one defined for C++ (C has no ASM directive), that is,
* a string literal in parenthesis.
*/
{
ExprNode* N;
/* Skip the ASM */
NextToken ();
/* Need left parenthesis */
ConsumeLParen ();
/* Create a new expression node and assign a void type */
N = AllocExprNode (NT_ASM, type_void, RVALUE);
/* String literal */
if (curtok != TOK_SCONST) {
/* Print an error */
Error (ERR_STRLIT_EXPECTED);
/* To be on the safe side later, insert an empty asm string */
AppendItem (N, xstrdup (""));
} else {
/* Insert a copy of the string into the expression node */
AppendItem (N, xstrdup (GetLiteral (curval)));
/* Reset the string pointer, effectivly clearing the string from the
* string table. Since we're working with one token lookahead, this
* will fail if the next token is also a string token, but that's a
* syntax error anyway, because we expect a right paren.
*/
ResetLiteralOffs (curval);
}
/* Skip the string token */
NextToken ();
/* Closing paren needed */
ConsumeRParen ();
/* Return the created node */
return N;
}
static ExprNode* Primary (void)
/* Evaluate a primary expression */
{
ExprNode* N;
/* Process a parenthesized subexpression. In this case we don't need to
* allocate a new node ourselves.
*/
if (curtok == TOK_LPAREN) {
NextToken ();
N = Expr0 ();
ConsumeRParen ();
return N;
}
/* Check for an integer or character constant */
if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
/* Create the new node */
N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
N->V.I = CurTok.IVal;
/* Skip the token and return the result */
NextToken ();
return N;
}
/* Check for a float constant */
if (curtok == TOK_FCONST) {
/* Create the new node */
N = AllocExprNode (NT_CONST, CurTok.Type, RVALUE);
N->V.F = CurTok.FVal;
/* Skip the token and return the result */
NextToken ();
return N;
}
/* All others may only be used if the expression evaluation is not called
* recursively by the preprocessor.
*/
if (Preprocessing) {
/* Illegal expression in PP mode */
Error (ERR_CPP_EXPR_EXPECTED);
/* Skip the token for error recovery */
NextToken ();
/* Return an integer constant */
return GetIntNode (0);
}
/* Identifier? */
if (curtok == TOK_IDENT) {
/* Identifier */
SymEntry* Sym;
ident Ident;
/* Get a pointer to the symbol table entry */
Sym = FindSym (CurTok.Ident);
/* Is the symbol known? */
if (Sym) {
/* We found the symbol - skip the name token */
NextToken ();
/* Check for illegal symbol types */
if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
/* Cannot use labels in expressions */
Error (ERR_SYMBOL_KIND);
return GetIntNode (0);
} else if (Sym->Flags & SC_TYPE) {
/* Cannot use type symbols */
Error (ERR_VAR_IDENT_EXPECTED);
/* Assume an int type to make lval valid */
return GetIntNode (0);
}
/* Handle enum values as constant integers */
if ((Sym->Flags & SC_ENUM) == SC_ENUM) {
N = GetIntNode (Sym->V.EnumVal);
} else {
/* All symbols besides functions and arrays are lvalues */
int LVal = (!IsTypeFunc (Sym->Type) && !IsTypeArray (Sym->Type));
/* Create the node */
N = AllocExprNode (NT_SYM, Sym->Type, LVal);
/* Set the symbol pointer */
SetNodeSym (N, Sym);
}
/* The symbol is referenced now */
Sym->Flags |= SC_REF;
} else {
/* We did not find the symbol. Remember the name, then skip it */
strcpy (Ident, CurTok.Ident);
NextToken ();
/* IDENT is either an auto-declared function or an undefined
* variable.
*/
if (curtok == TOK_LPAREN) {
/* Warn about the use of a function without prototype */
Warning (WARN_FUNC_WITHOUT_PROTO);
/* Declare a function returning int. For that purpose, prepare
* a function signature for a function having an empty param
* list and returning int.
*/
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
N = AllocExprNode (NT_SYM, Sym->Type, RVALUE);
SetNodeSym (N, Sym);
} else {
/* Print an error about an undeclared variable */
Error (ERR_UNDEFINED_SYMBOL, Ident);
/* Undeclared Variable */
Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
N = AllocExprNode (NT_SYM, Sym->Type, LVALUE);
SetNodeSym (N, Sym);
}
}
} else if (curtok == TOK_SCONST) {
/* String literal */
N = AllocExprNode (NT_CONST, GetCharArrayType (strlen (GetLiteral (curval))), RVALUE);
N->V.I = curval;
} else if (curtok == TOK_ASM) {
/* ASM statement? */
N = DoAsm ();
} else if (curtok == TOK_A) {
/* A register */
N = AllocExprNode (NT_REG_A, type_uchar, LVALUE);
} else if (curtok == TOK_X) {
/* X register */
N = AllocExprNode (NT_REG_X, type_uchar, LVALUE);
} else if (curtok == TOK_Y) {
/* Y register */
N = AllocExprNode (NT_REG_Y, type_uchar, LVALUE);
} else if (curtok == TOK_AX) {
/* AX pseudo register */
N = AllocExprNode (NT_REG_AX, type_uint, LVALUE);
} else if (curtok == TOK_EAX) {
/* EAX pseudo register */
N = AllocExprNode (NT_REG_EAX, type_ulong, LVALUE);
} else {
/* Illegal primary. */
Error (ERR_EXPR_EXPECTED);
N = GetIntNode (0);
}
/* Return the new node */
return N;
}
static ExprNode* DoArray (ExprNode* Left)
/* Handle arrays */
{
ExprNode* Right;
ExprNode* Root;
type* ElementType;
/* Skip the bracket */
NextToken ();
/* Get the index */
Right = Expr0 ();
/* Check the types. As special "C" feature, accept a reversal of base and
* index types:
* char C = 3["abcdefg"];
* is legal C!
*/
if (IsClassPtr (Left->Type)) {
/* Right side must be some sort of integer */
if (!IsClassInt (Right->Type)) {
/* Print an error */
Error (ERR_CANNOT_SUBSCRIPT);
/* To avoid problems later, create a new, legal subscript
* expression
*/
Right = GetIntNode (0);
}
} else if (IsClassPtr (Right->Type)) {
ExprNode* Tmp;
/* Left side must be some sort of integer */
if (!IsClassInt (Right->Type)) {
/* Print an error */
Error (ERR_CANNOT_SUBSCRIPT);
/* To avoid problems later, create a new, legal subscript
* expression
*/
Left = GetIntNode (0);
}
/* Swap the expression to it's normal form */
Tmp = Right;
Right = Left;
Left = Tmp;
} else {
/* Invalid array expression. Skip the closing bracket, then return
* an integer instead of the array expression to be safe later.
*/
Error (ERR_CANNOT_SUBSCRIPT);
ConsumeRBrack ();
return GetIntNode (0);
}
/* Skip the right bracket */
ConsumeRBrack ();
/* Get the type of the array elements */
ElementType = Indirect (Left->Type);
/* Allocate the branch node for the array expression */
Root = AllocExprNode (NT_ARRAY_SUBSCRIPT,
ElementType,
IsTypeArray (ElementType)? RVALUE : LVALUE);
/* Setup the branches */
SetLeftNode (Root, Left);
SetRightNode (Root, Right);
/* ...and return it */
return Root;
}
static ExprNode* DoStruct (ExprNode* Left)
/* Process struct field access */
{
nodetype_t NT;
ident Ident;
type* StructType;
ExprNode* Right;
ExprNode* Root;
SymEntry* Field;
/* Type check */
StructType = Left->Type;
if (curtok == TOK_PTR_REF) {
NT = NT_STRUCTPTR_ACCESS;
if (!IsTypePtr (StructType)) {
Error (ERR_STRUCT_PTR_EXPECTED);
return GetIntNode (0);
}
StructType = Indirect (StructType);
} else {
NT = NT_STRUCT_ACCESS;
}
if (!IsClassStruct (StructType)) {
Error (ERR_STRUCT_EXPECTED);
return GetIntNode (0);
}
/* Skip the token and check for an identifier */
NextToken ();
if (curtok != TOK_IDENT) {
/* Print an error */
Error (ERR_IDENT_EXPECTED);
/* Return an integer expression instead */
return GetIntNode (0);
}
/* Get the symbol table entry and check for a struct field */
strcpy (Ident, CurTok.Ident);
NextToken ();
Field = FindStructField (StructType, Ident);
if (Field == 0) {
/* Struct field not found */
Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
/* Return an integer expression instead */
return GetIntNode (0);
}
/* Allocate and set up the right (== field) node */
Right = AllocExprNode (NT_SYM, Field->Type, RVALUE);
SetNodeSym (Right, Field);
/* Allocate the branch node for the resulting expression */
Root = AllocExprNode (NT, Right->Type,
IsTypeArray (Right->Type)? RVALUE : LVALUE);
/* Setup the branches */
SetLeftNode (Root, Left);
SetRightNode (Root, Right);
/* ...and return it */
return Root;
}
static ExprNode* DoFunctionCall (ExprNode* Left)
/* Process a function call */
{
type* ResultType; /* Type of function result */
FuncDesc* Func; /* Function descriptor */
ExprNode* Root; /* Function call node */
int Ellipsis; /* True if we have an open param list */
SymEntry* Param; /* Current formal parameter */
unsigned ParamCount; /* Actual parameter count */
unsigned ParamSize; /* Number of parameter bytes */
/* Type check */
if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
/* Call to non function */
Error (ERR_ILLEGAL_FUNC_CALL);
/* Free the old node */
FreeExprNode (Left);
/* Return something safe */
return GetIntNode (0);
}
/* Get the type of the function result */
ResultType = Left->Type;
if (IsTypeFuncPtr (Left->Type)) {
++ResultType;
}
ResultType += DECODE_SIZE + 1; /* Set to result type */
/* Skip the opening parenthesis */
NextToken ();
/* Allocate the function call node */
Root = AllocExprNode (NT_FUNCTION_CALL, ResultType, RVALUE);
/* Get a pointer to the function descriptor from the type string */
Func = GetFuncDesc (Left->Type);
/* Initialize vars to keep gcc silent */
Param = 0;
/* Parse the parameter list */
ParamSize = 0;
ParamCount = 0;
Ellipsis = 0;
while (curtok != TOK_RPAREN) {
/* Count arguments */
++ParamCount;
/* Fetch the pointer to the next argument, check for too many args */
if (ParamCount <= Func->ParamCount) {
if (ParamCount == 1) {
/* First argument */
Param = Func->SymTab->SymHead;
} else {
/* Next argument */
Param = Param->NextSym;
CHECK ((Param->Flags & SC_PARAM) != 0);
}
} else if (!Ellipsis) {
/* Too many arguments. Do we have an open param list? */
if ((Func->Flags & FD_ELLIPSIS) == 0) {
/* End of param list reached, no ellipsis */
Error (ERR_TOO_MANY_FUNC_ARGS);
}
/* Assume an ellipsis even in case of errors to avoid an error
* message for each other argument.
*/
Ellipsis = 1;
}
/* Get the parameter value expression tree and add it to the parameter
* list. (### check expr level)
*/
AppendItem (Root, Expr1 ());
/* Check for end of argument list */
if (curtok != TOK_COMMA) {
break;
}
NextToken ();
}
/* We need the closing bracket here */
ConsumeRParen ();
/* Check if we had enough parameters */
if (ParamCount < Func->ParamCount) {
Error (ERR_TOO_FEW_FUNC_ARGS);
}
/* Return the function call node */
return Root;
}
static ExprNode* PostfixExpr (void)
{
/* Get the lower level expression */
ExprNode* Root = Primary ();
/* */
while (curtok == TOK_LBRACK || curtok == TOK_LPAREN ||
curtok == TOK_DOT || curtok == TOK_PTR_REF ||
curtok == TOK_INC || curtok == TOK_DEC) {
/* This is for us */
switch (curtok) {
case TOK_LBRACK:
Root = DoArray (Root);
break;
case TOK_LPAREN:
Root = DoFunctionCall (Root);
break;
case TOK_DOT:
case TOK_PTR_REF:
Root = DoStruct (Root);
break;
case TOK_INC:
break;
case TOK_DEC:
break;
default:
Internal ("Unexpected token");
}
}
/* Return the result */
return Root;
}
static ExprNode* DoPreIncDec (void)
/* Handle preincrement and predecrement */
{
ExprNode* Op;
ExprNode* Root;
/* Determine the type of the node */
nodetype_t NT = (curtok == TOK_INC)? NT_PRE_INC : NT_PRE_DEC;
/* Skip the operator token */
NextToken ();
/* Get the expression to increment or decrement */
Op = UnaryExpr ();
/* The operand must be an lvalue */
if (Op->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 Op;
}
/* Setup the expression tree */
Root = AllocExprNode (NT, Op->Type, RVALUE);
SetLeftNode (Root, Op);
/* Return the new node */
return Root;
}
static ExprNode* DoUnaryPlusMinus (void)
/* Handle unary +/- */
{
ExprNode* Op;
ExprNode* Root;
/* Remember the current token for later, then skip it */
token_t Tok = curtok;
NextToken ();
/* Get the operand */
Op = UnaryExpr ();
/* Type check */
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
/* Display diagnostic */
Error (ERR_SYNTAX);
/* Free the errorneous node */
FreeExprNode (Op);
/* Return something that makes sense later */
return GetIntNode (0);
}
/* In case of PLUS, we must do nothing */
if (Tok == TOK_PLUS) {
/* Use the operand unchanged */
Root = Op;
} else {
/* Setup the expression tree */
Root = AllocExprNode (NT_UNARY_MINUS, Op->Type, RVALUE);
SetLeftNode (Root, Op);
}
/* Return the new node */
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_SIZEOF || IsTypeExpr ()) {
/* Check the token */
switch (curtok) {
case TOK_INC:
case TOK_DEC:
return DoPreIncDec ();
case TOK_PLUS:
case TOK_MINUS:
return DoUnaryPlusMinus ();
case TOK_AND:
break;
case TOK_STAR:
break;
case TOK_COMP:
break;
case TOK_BOOL_NOT:
break;
case TOK_SIZEOF:
break;
default:
break;
}
} else {
/* Call the lower level */
return PostfixExpr ();
}
}

64
src/cc65/parser.h Normal file
View File

@ -0,0 +1,64 @@
/*****************************************************************************/
/* */
/* parser.h */
/* */
/* Expression parser */
/* */
/* */
/* */
/* (C) 2000 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@musoftware.de */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef PARSER_H
#define PARSER_H
#include "exprnode.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
ExprNode* DoAsm (void);
/* This function parses ASM statements. The syntax of the ASM directive
* looks like the one defined for C++ (C has no ASM directive), that is,
* a string literal in parenthesis.
*/
/* End of parser.h */
#endif

View File

@ -129,7 +129,7 @@ typedef enum token_t {
TOK_FASTCALL,
TOK_A,
TOK_X,
TOK_Y,
TOK_Y,
TOK_AX,
TOK_EAX,
@ -148,10 +148,11 @@ typedef enum token_t {
typedef struct Token_ Token;
struct Token_ {
token_t Tok; /* The token itself */
long IVal; /* The integer attribute */
long IVal; /* The integer attribute */
double FVal; /* The float attribute */
ident Ident; /* Identifier if IDENT */
unsigned Pos; /* Source line where the token comes from */
type* IType; /* Type if integer constant */
type* Type; /* Type if integer or float constant */
};
extern Token CurTok; /* The current token */
@ -161,12 +162,12 @@ extern Token NextTok; /* The next token */
#define curtok CurTok.Tok
#define curval CurTok.IVal
#define curpos CurTok.Pos
#define curtype CurTok.IType
#define curtype CurTok.Type
#define nxttok NextTok.Tok
#define nxtval NextTok.IVal
#define nxtpos NextTok.Pos
#define nxttype NextTok.IType
#define nxttype NextTok.Type