Removed dep on API
[ninja.git] / src / op5 / ninja_sdk / parsegen / LalrState.php
blob7060c47442bf9f9bd552f4f3ef6c767b3d1762f0
1 <?php
3 class LalrState {
4 private $items; /* kernel */
5 private $grammar;
7 public function __construct( $items, $grammar ) {
8 if( !is_array( $items ) )
9 $items = array( $items );
11 $this->items = $items;
12 $this->grammar = $grammar;
15 public function next_symbols() {
16 $symbols = array();
17 foreach( $this->closure() as $item ) {
18 $next = $item->next();
19 if( $next !== false && !in_array( $next, $symbols ) ) {
20 $symbols[] = $next;
23 return $symbols;
26 public function take( $symbol ) {
27 $next_items = array();
28 foreach( $this->closure() as $item ) {
29 $next_item = $item->take( $symbol );
30 if( $next_item !== false ) {
31 $next_items[] = $next_item;
34 return new self( $next_items, $this->grammar );
37 public function closure() {
38 $items = $this->items;
40 /* Don't use foreach. $items can grow in the loop, and the new items needs to be handled too */
41 for( $i = 0; $i<count($items); $i++ ) {
42 $cur_item = $items[$i];
43 $next_symbol = $cur_item->next();
44 if( $next_symbol === false ) {
46 } else {
47 foreach( $this->grammar->productions( $next_symbol ) as $new_item ) {
48 $add = true;
49 foreach( $items as $test_item ) {
50 if( $test_item->equals($new_item) ) {
51 $add = false;
54 if( $add ) {
55 $items[] = $new_item;
60 return $items;
63 public function errors() {
64 $items = $this->items;
66 $errors = array();
67 /* Don't use foreach. $items can grow in the loop, and the new items needs to be handled too */
68 for( $i = 0; $i<count($items); $i++ ) {
69 $cur_item = $items[$i];
70 $next_symbol = $cur_item->next();
71 $rule = $this->grammar->errors($next_symbol);
72 if($rule) {
73 foreach( $rule->follow() as $follow ) {
74 $errors[$follow] = $rule;
78 return $errors;
81 public function __toString() {
82 $outp = "";
83 foreach( $this->closure() as $item ) {
84 $outp .= "$item\n";
86 return $outp;
89 public function equals( $state ) {
90 if( count( $this->items ) != count( $state->items ) ) {
91 return false;
93 foreach( $this->items as $itema ) {
94 $exists = false;
95 foreach( $state->items as $itemb ) {
96 if( $itema->equals( $itemb ) ) {
97 $exists = true;
100 if( $exists == false )
101 return false;
103 return true;