00001 #ifndef wali_nwa_NESTED_WORD_HPP 00002 #define wali_nwa_NESTED_WORD_HPP 00003 00004 #include "wali/Countable.hpp" 00005 #include "opennwa/NwaFwd.hpp" 00006 #include <vector> 00007 #include <algorithm> 00008 00009 namespace opennwa 00010 { 00011 /// This class represents a single nested word. 00012 /// 00013 /// The word can be unbalanced left or unbalanced right, even 00014 /// though our NWAs do not have support for unbalanced-right 00015 /// words. 00016 /// 00017 /// The representation used by this class is closer to that of a 00018 /// word in a visibly-pushdown language. It holds the linear 00019 /// contents of a word, but does not store the nesting relation 00020 /// explicitly. Instead, each position in the word is annotated 00021 /// with whether it is an internal, call, or return position. The 00022 /// nesting relation is induced by the matchings between calls and 00023 /// returns. 00024 class NestedWord : public wali::Countable 00025 { 00026 public: 00027 /// Each position in the nested word has a symbol and a type. 00028 /// 00029 struct Position 00030 { 00031 /// The type of a position: either a call position, internal 00032 /// position, or return position. 00033 enum Type { 00034 CallType, InternalType, ReturnType 00035 }; 00036 00037 /// The symbol at this position 00038 /// 00039 Symbol symbol; 00040 00041 /// The type (call/internal/return) of this position 00042 /// 00043 Type type; 00044 00045 /// Constructs a Position object with the given symbol and 00046 /// type 00047 Position(Symbol sym, Type ty) : symbol(sym), type(ty) {} 00048 00049 /// Returns whether two positions are equal 00050 /// 00051 bool operator==(Position const & p) const 00052 { 00053 return symbol == p.symbol && type == p.type; 00054 } 00055 }; 00056 00057 private: 00058 std::vector<Position> word; 00059 00060 public: 00061 /// An iterator to allow traversal through the word. (Don't 00062 /// depend on this concrete type specifically, but I guarantee 00063 /// it will be a random access iterator.) 00064 typedef std::vector<Position>::const_iterator const_iterator; 00065 00066 /// Appends the position 'p' (symbol & type) to the end of this 00067 /// nested word 00068 void append(Position p) 00069 { 00070 word.push_back(p); 00071 } 00072 00073 00074 /// Appends the given symbol to the end of this nested word in a 00075 /// call position. 00076 void appendCall(Symbol sym) { append(Position(sym, Position::CallType)); } 00077 /// Appends the given symbol to the end of this nested word in an 00078 /// internal position. 00079 void appendInternal(Symbol sym) { append(Position(sym, Position::InternalType)); } 00080 /// Appends the given symbol to the end of this nested word in a 00081 /// return position. 00082 void appendReturn(Symbol sym) { append(Position(sym, Position::ReturnType)); } 00083 00084 00085 /// Returns an iterator to the first position in this nested 00086 /// word. 00087 const_iterator begin() const 00088 { 00089 return word.begin(); 00090 } 00091 00092 /// Returns an iterator to one position past the end of this 00093 /// nested word. 00094 const_iterator end() const 00095 { 00096 return word.end(); 00097 } 00098 00099 /// 00100 /// Returns the number of positions in this nested word 00101 size_t size() const 00102 { 00103 return word.size(); 00104 } 00105 00106 /// 00107 /// Returns whether the two nested words are equal 00108 bool operator==(NestedWord const & other) const 00109 { 00110 if (word.size() != other.word.size()) { 00111 return false; 00112 } 00113 else { 00114 return std::equal(word.begin(), word.end(), other.word.begin()); 00115 } 00116 } 00117 00118 /// 00119 /// Returns whether two nested words are unequal 00120 bool operator!=(NestedWord const & other) const 00121 { 00122 return !(*this == other); 00123 } 00124 00125 }; 00126 00127 00128 typedef ref_ptr<NestedWord> NestedWordRefPtr; 00129 } 00130 00131 00132 // Yo, Emacs! 00133 // Local Variables: 00134 // c-file-style: "ellemtel" 00135 // c-basic-offset: 2 00136 // End: 00137 00138 #endif