1 module gamma.input.earley.ItemSet; 2 3 import gamma.grammar.Alternative; 4 import gamma.grammar.Grammar; 5 import gamma.grammar.Nonterminal; 6 import gamma.grammar.Symbol; 7 import gamma.util.Indexed; 8 import gamma.input.earley.Item; 9 10 class ItemSet : Indexed 11 { 12 private Item[] items_; 13 14 private size_t index_; 15 16 public static ItemSet initialItemSet(Alternative alternative, Grammar grammar) 17 { 18 ItemSet itemSet = new ItemSet(0); 19 Item item = Item.initialItem(alternative, itemSet); 20 21 itemSet.items_ ~= item; 22 itemSet.closure(grammar); 23 return itemSet; 24 } 25 26 public static ItemSet nextItemSet(ItemSet prevItemSet, Symbol symbol, Grammar grammar) 27 { 28 ItemSet itemSet = new ItemSet(prevItemSet.index_ + 1); 29 30 foreach (item; prevItemSet.items_) 31 if (item.symbol == symbol) 32 itemSet.items_ ~= Item.nextItem(item, null); 33 itemSet.closure(grammar); 34 return itemSet; 35 } 36 37 private this(size_t index) 38 { 39 this.index_ = index; 40 } 41 42 public Item[] items() 43 { 44 return this.items_; 45 } 46 47 public override size_t index() const @nogc nothrow pure @safe 48 { 49 return this.index_; 50 } 51 52 private void closure(Grammar grammar) 53 { 54 size_t length; 55 56 // TODO: repetition only for self referential final items 57 58 do 59 { 60 length = this.items_.length; 61 for (int i = 0; i < this.items_.length; ++i) 62 { 63 Item item = this.items_[i]; 64 65 if (item.isFinal) 66 { 67 Symbol lhsSymbol = item.alternative.lhs.symbol; 68 ItemSet parent = item.parent; 69 70 for (int j = 0; j < parent.items_.length; ++j) 71 { 72 Item parentItem = parent.items_[j]; 73 74 if (parentItem.symbol == lhsSymbol) 75 add(Item.nextItem(parentItem, item)); 76 } 77 } else if (cast(Nonterminal) item.symbol) 78 { 79 Nonterminal nonterminal = cast(Nonterminal) item.symbol; 80 Alternative[] alternatives = grammar.ruleOf(nonterminal).alternatives; 81 82 foreach (alternative; alternatives) 83 add(Item.initialItem(alternative, this)); 84 } 85 } 86 } 87 while (this.items_.length > length); 88 } 89 90 private void add(Item item) 91 { 92 // TODO: report ambiguities 93 94 foreach (otherItem; this.items_) 95 if (item.matches(otherItem)) 96 return; 97 this.items_ ~= item; 98 } 99 100 public override string toString() const 101 { 102 import std.format : format; 103 104 return format!"{%-(\n\t%s,%)\n}"(this.items_); 105 } 106 }