Synopsis - Cross-Reference

File: /Synopsis/Parsers/Cxx/Dictionary.cc
  1//
  2// Copyright (C) 2001 Stephen Davies
  3// Copyright (C) 2001 Stefan Seefeld
  4// All rights reserved.
  5// Licensed to the public under the terms of the GNU LGPL (>= 2),
  6// see the file COPYING for details.
  7//
  8
  9#include "Dictionary.hh"
 10#include "ASG.hh"
 11#include "Types.hh"
 12
 13#include <map>
 14#include <vector>
 15#include <list>
 16#include <string>
 17#include <iostream>
 18#include <cassert>
 19
 20typedef std::multimap<std::string, Types::Named*> name_map;
 21
 22//. Define nested class
 23struct Dictionary::Data
 24{
 25    name_map map;
 26};
 27
 28//. Constructor
 29Dictionary::Dictionary()
 30{
 31    m = new Data;
 32}
 33
 34//. Destructor
 35Dictionary::~Dictionary()
 36{
 37    delete m;
 38}
 39
 40//. Quick check if the name is in the dict
 41bool
 42Dictionary::has_key(const std::string& name)
 43{
 44    return m->map.find(name) != m->map.end();
 45}
 46
 47//. Lookup single
 48//. TODO: the forward filtering could probably be done much simpler!
 49//. TODO: The exception throwing is heavy too, besides all the vector copying!
 50Types::Named*
 51Dictionary::lookup(const std::string& name)
 52{
 53    name_map::iterator iter = m->map.lower_bound(name);
 54    name_map::iterator end = m->map.upper_bound(name);
 55
 56    // Check for not found
 57    if (iter == end)
 58        throw KeyError(name);
 59
 60    Types::Named* type = iter->second;
 61    if (++iter == end)
 62        return type;
 63
 64    // Check for Unknown types
 65    if (dynamic_cast<Types::Unknown*>(type))
 66    {
 67        // Skip further unknown types
 68        while (iter != end && dynamic_cast<Types::Unknown*>(iter->second))
 69            ++iter;
 70        if (iter == end)
 71            // No choice but to return the Unknown
 72            return type;
 73        type = (iter++)->second;
 74        // Any other types that aren't unknown cause error
 75        while (iter != end && dynamic_cast<Types::Unknown*>(iter->second))
 76            ++iter;
 77        if (iter == end)
 78            // No more non-Unknown types, so return the one we found
 79            return type;
 80    }
 81    // Create exception object
 82    MultipleError exc(name);
 83    exc.types.push_back(type);
 84    do
 85        exc.types.push_back(iter->second);
 86    while (++iter != end);
 87    throw exc;
 88}
 89
 90//. Lookup multiple
 91std::vector<Types::Named*>
 92Dictionary::lookupMultiple(const std::string& name) throw (KeyError)
 93{
 94    name_map::iterator iter = m->map.lower_bound(name);
 95    name_map::iterator end = m->map.upper_bound(name);
 96
 97    // Check for not found
 98    if (iter == end)
 99        throw KeyError(name);
100
101    // Store type pointers in a vector
102    std::vector<Types::Named*> types;
103    do
104        types.push_back(iter->second);
105    while (++iter != end);
106    return types;
107}
108
109void
110Dictionary::insert(Types::Named* type)
111{
112    std::string key = type->name().back();
113    m->map.insert(name_map::value_type(key, type));
114}
115
116void
117Dictionary::insert(ASG::Declaration* decl)
118{
119    Types::Declared* declared = new Types::Declared(decl->name(), decl);
120    insert(declared);
121    if (ASG::Function* func = dynamic_cast<ASG::Function*>(decl))
122        // Also insert real (unmangled) name of functions
123        m->map.insert(name_map::value_type(func->realname(), declared));
124}
125
126void
127Dictionary::dump()
128{
129    name_map::iterator iter = m->map.begin(), end = m->map.end();
130    std::cout << "Dumping dictionary: " << m->map.size() << " items.\n";
131    while (iter != end)
132    {
133        name_map::value_type p = *iter++;
134        std::cout << "   " << p.first << "\t-> " << p.second->name() << "\n";
135    }
136    std::cout.flush();
137}
138// vim: set ts=8 sts=4 sw=4 et: