+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 */
{
+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 */
{
#include <stdio.h>
+/* common */
+#include "attrib.h"
+
/*****************************************************************************/
* 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 */
#define ERROR_H
+
+/* common */
+#include "attrib.h"
+
+
/*****************************************************************************/
/* Data */
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);
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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;
+}
+
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
-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);
+}
+
+
+
+
+/* common */
+#include "coll.h"
+
+/* cc65 */
#include "datatype.h"
/*****************************************************************************/
-/* Forwards */
+/* Forwards */
/*****************************************************************************/
+struct ExprHeap;
struct SymEntry;
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 */
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, /* + */
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 */
declare.o \
error.o \
expr.o \
+ exprheap.o \
exprnode.o \
- exprtree.o \
funcdesc.o \
function.o \
global.o \
clean:
rm -f *~ core *.map
-
+
zap: clean
rm -f *.o $(EXECS) .depend
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 \
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
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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 ();
+
+ }
+}
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
TOK_FASTCALL,
TOK_A,
TOK_X,
- TOK_Y,
+ TOK_Y,
TOK_AX,
TOK_EAX,
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 */
#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