00001
00002
00003 #include "enum.h"
00004 #include "enum_i.h"
00005
00006
00007 #line 28 "enum.cpp"
00008
00019 Enum_symbol::Enum_symbol()
00020 {
00021 set_status(st_Declared);
00022 }
00023
00024 #line 43 "enum.cpp"
00025
00026
00027 Enum_symbol::~Enum_symbol()
00028 { }
00029
00030 #line 47 "enum.cpp"
00031
00032 Symbol::Kind
00033 Enum_symbol::get_kind() const
00034 {
00035 return k_Enum;
00036 }
00037
00038 #line 53 "enum.cpp"
00039
00044 Ptree*
00045 Enum_symbol::process_value(Ptree* tree, Ptree* previous, Abstract_scope* scope)
00046 {
00047
00048 Ptree *name, *init;
00049 if (tree->IsLeaf()) {
00050 name = tree;
00051 if (!previous)
00052 init = new Leaf("0", 1);
00053 else
00054 init = new PtreeInfixExpr(previous, Ptree::List(new Leaf("+", 1), new Leaf("1", 1)));
00055 } else {
00056 expect_ptree(tree->Second(), '=');
00057 name = tree->First();
00058 init = tree->Third();
00059 }
00060
00061 assert(name->IsLeaf());
00062
00063
00064
00065
00066
00067
00068
00069 Expr_result res = Expr_annotator(scope, &Source::instance()).visit(init);
00070 res.do_integral_promotions();
00071
00072 if (!res.get_type().is_int())
00073 compile_error("enum initializer must be integer or enum");
00074
00075 Variable_symbol* vsym = new Variable_symbol(get_type(),
00076 s_None,
00077 res.get_tree(),
00078 0,
00079 false);
00080 scope->add_symbol(std::string(name->ToString()), vsym);
00081 values.push_back(vsym);
00082
00083 Token t = { name->GetPosition(), name->GetLength(), ntName };
00084 return new LeafName(t);
00085 }
00086
00087 #line 100 "enum.cpp"
00088
00091 Type
00092 parse_enum(Ptree* tree, Abstract_scope* scope, Ptree* name_for_anon)
00093 {
00094 expect_ptree(tree->First(), "enum");
00095
00096 Ptree* nametree = tree->Second();
00097 Ptree* content = tree->Third();
00098
00099
00100
00101 if (!content) {
00102 if (!nametree)
00103 compile_error("stray `enum' in program");
00104
00105 Symbol_pair sym = Symbol_name(nametree, scope, false).lookup_for_use(false);
00106 if (!sym.tag || sym.tag->get_kind() != Symbol::k_Enum)
00107 compile_error("`enum " + std::string(nametree->ToString()) + "' not defined");
00108 return downcast<Enum_symbol*>(sym.tag)->get_type();
00109 }
00110
00111
00112 std::string name;
00113 if (!nametree)
00114 nametree = name_for_anon;
00115
00116 Symbol_name sname(nametree, scope, false);
00117 if (sname.is_qualified())
00118 compile_error("qualified name not allowed in definition");
00119 if (sname.is_template())
00120 compile_error("template enum");
00121 name = sname.get_name();
00122
00123 Enum_symbol* sym;
00124 Symbol_pair pair;
00125 if ((pair = scope->lookup_here(name, true)) && pair.tag) {
00126 if (pair.tag->get_kind() != Symbol::k_Enum)
00127 compile_error("`" + name + "' already defined");
00128 sym = downcast<Enum_symbol*>(pair.tag);
00129 } else {
00130 sym = new Enum_symbol();
00131 scope->add_symbol(name, sym);
00132 }
00133
00134 if (sym->is_defined())
00135 compile_error("`enum " + name + "' already defined");
00136
00137
00138 assert(!content->IsLeaf());
00139 expect_ptree(content->First(), '{');
00140 expect_ptree(content->Third(), '}');
00141
00142 Ptree* previous = 0;
00143 for (Ptree* p = content->Second(); p; (p = p->Cdr()) && (p = p->Cdr())) {
00144 previous = sym->process_value(p->Car(), previous, scope);
00145 }
00146
00147 sym->set_defined();
00148 return sym->get_type();
00149 }