/* Auxiliary lexical routines */ #include #include #include #include "utils.h" #include "AST.h" #include "tokens.h" bool error_column = true; File::Coordinates File::coordinates( unsigned long offset ) const { if (offset == 0) return Coordinates( 0, 0 ); else { /* const unsigned long *lower = lower_bound( lineEndings.begin(), lineEndings.end(), offset, less< unsigned long >() ); */ vector::const_iterator lower = lower_bound( lineEndings.begin(), lineEndings.end(), offset, less< unsigned long >() ); return Coordinates( lower - lineEndings.begin(), offset - *(lower - 1) ); } } /* Record that N is the position of a newline in the source program */ /* file. It is assumed that this function is called with increasing */ /* values of N. */ void File::defineLineEnd (unsigned long N) { lineEndings.push_back (N); } string SourcePosn::asString() const { ostringstream formatter; formatter << *this; return formatter.str(); } /* Print a position in a format suitable for errors or warnings. */ ostream & operator << ( ostream &os, const SourcePosn &position ) { if (position.unknown()) os << "?: "; else { const SourcePosn::Coordinates coordinates = position.coordinates(); os << *position.file << ':' << coordinates.first; if (error_column) os << ':' << coordinates.second; } return os; } /* An array type with given ELEMENTTYPE and DIMS dimensions. When */ /* DIMS=0, equals ELEMENTTYPE. */ TypeNode* makeArrayType (TypeNode* elementType, int dims) { while (dims > 0) { elementType = new JavaArrayTypeNode (elementType); dims -= 1; } return elementType; } struct InternTableEntry { InternTableEntry(string* datum0, InternTableEntry* next0) : datum(datum0), next(next0) {} InternTableEntry(const char* datum0, InternTableEntry* next0) : datum(new string(datum0)), next(next0) {} string* datum; InternTableEntry* next; }; static InternTableEntry** internTable; static int internTableSize = 0; static unsigned int pjw_hash (const char* x, size_t n, size_t k) { unsigned int r; const char* lim = x+n; for (r = 0; x != lim; x += 1) { r = (r << 4) + *x; if (r > 0x0fffffff) { r ^= (r >> 24) & 0xf0; r &= 0x0fffffff; } } return r % k; } static void createInternTable() { if (internTable == NULL) { internTableSize = 1019; internTable = new InternTableEntry*[internTableSize]; for (int i = 0; i < internTableSize; i++) internTable[i] = NULL; } } /* The unique string* containing the current contents of TEXT. */ const string* intern (const char* text, size_t len) { createInternTable(); unsigned int h = pjw_hash(text, len, internTableSize); InternTableEntry** p; for (p = &internTable[h]; *p != NULL; p = &(*p)->next) { if (text == *(*p)->datum) return (*p)->datum; } *p = new InternTableEntry(new string(text, len), *p); return (*p)->datum; } /* The unique string* containing the current contents of TEXT. */ const string* intern (const char* text) { return intern(text, strlen(text)); } /* The unique string* containing the current contents of TEXT. */ const string* intern (const string& text) { return intern(text.c_str(), text.size()); } /* Parse array access/array type stuff */ TreeNode *TreeNode::asExpr() { unimplemented("asExpr"); return NULL; } TreeNode *TreeNode::asExpr2(TreeNode *) { unimplemented("asExpr2"); return NULL; } TypeNode *TreeNode::asType() { unimplemented("asType"); return NULL; } static void noQualifiers(const TreeNode *t) { if (t->flags()) t->error() << "Unexpected qualifiers " << stringifyModifiers(t->flags()) << endl; } TreeNode *ArrayNameNode::asExpr() { TreeNode *base = new ObjectNode(name()); TreeNode *aspecs = arrayspecifiers(); int a = aspecs->arity(); noQualifiers(this); for (int i = 0; i < a; ) base = aspecs->child(i++)->asExpr2(base); name(0); free(); return base; } TypeNode *ArrayNameNode::asType() { TypeNode *base = new TypeNameNode(name()); TreeNode *aspecs = arrayspecifiers(); base->modifiers(flags()); for (int i = aspecs->arity(); i > 0; ) base = aspecs->child(--i)->asType2(base); name(0); free(); return base; } TypeNode *arraySpecifiers2Type(llist *aspecs, TypeNode *base) { foreach (aspec, llist, *dreverse(aspecs)) { base = (*aspec)->asType2(base); (*aspec)->free(); } free_all(aspecs); return base; } TreeNode *EmptyArrayNode::asExpr2(TreeNode *array) { error() << "Missing index expression" << endl; return array; } TypeNode *EmptyArrayNode::asType2(TypeNode *base) { TypeNode *t = new JavaArrayTypeNode(base); t->modifiers(flags()); return t; } TreeNode *ExpressionArrayNode::asExpr2(TreeNode *array) { noQualifiers(this); TreeNode * const expression = expr(); expr(0); return new ArrayAccessNode(array, expression); } TypeNode *ExpressionArrayNode::asType2(TypeNode *base) { /* This is an error, except if the expression is: - a double literal of the form nd (n a positive integer) - (id.id...)d (a cast) */ TypeNode *t = expr()->asType2(base); t->modifiers(flags()); return t; } TypeNode *TreeNode::asType2(TypeNode *base) { error() << "type expected" << endl; return base; } TypeNode *PointNode::asType2(TypeNode *base) { if (args()->arity() != 1) return TreeNode::asType2(base); else return args()->child(0)->asType2(base); } TypeNode *PrimitiveLitNode::asType2(TypeNode *base) { Literal l = literal(); if (l.isNd()) // Note that integral doubles are represented exactly... return new TitaniumArrayTypeNode (base, new PrimitiveLitNode((int32)l.doubleValue())); return TreeNode::asType2(base); } bool TreeNode::isd() const { return false; } bool ObjectNode::isd() const { TreeNode *n = name(); return n->qualifier()->absent() && *n->ident() == "d"; } bool TypeNameNode::isNamedType() const { return true; } bool TemplateInstanceTypeNode::isNamedType() const { return true; } TypeNode *CastNode::asType2(TypeNode *base) { TypeNode *dt = dtype(); if (opnd0()->isd() && dt->isNamedType() && !dt->modifiers()) return new TitaniumArrayTypeNode(base, new ObjectNode(dt->name())); return TreeNode::asType2(base); } TreeNode *TitaniumArrayNode::asExpr2(TreeNode *array) { error() << "unexpected identifier 'd'" << endl; TreeNode *expression = expr(); expr(0); return new ArrayAccessNode(array, new PointNode(cons(expression))); } TypeNode *TitaniumArrayNode::asType2(TypeNode *base) { TreeNode * const expression = expr(); expr(0); TypeNode *t = new TitaniumArrayTypeNode(base, expression); t->modifiers(flags()); return t; } llist* makeVarDeclNodes(bool isfinal, TypeNode *type, llist *decls) { llist *dlist = NULL; foreach (decl, llist, *decls) { dlist = cons(static_cast (new VarDeclNode(isfinal, makeArrayType(type, (*decl).dims), (*decl).name, (*decl).initExpr)), dlist); } free_all(decls); return dlist; } static NameNode *buildName_help(NameNode *base, const char *fullname, SourcePosn pos) { const char *pt = strchr(fullname,'.'); assert(pt != fullname); if (pt) { char tmp[255]; strncpy(tmp, fullname, pt - fullname); tmp[pt - fullname] = '\0'; return buildName_help(new NameNode (base, intern(tmp), NULL, pos), pt+1, pos); } else { return new NameNode (base, intern(fullname), NULL, pos); } } extern NameNode *buildName(const char *fullname, SourcePosn pos) { return buildName_help((NameNode *)TreeNode::omitted, fullname, pos); }