source: Dev/trunk/src/client/util/docscripts/lib/parser2/Scope.php

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 5.5 KB
Line 
1<?php
2
3require_once('Destructable.php');
4
5class Scope extends Destructable {
6  protected $_parent;
7  protected $definitions = array();
8  protected $assignments = array();
9
10  public function __destruct() {
11    $this->mem_flush('_parent', 'definitions', 'assignments');
12  }
13
14  /**
15   * Turns a name symbol into a variable symbol
16   *
17   * @param Symbol $symbol A name object occurring in the current scope
18   */
19  public function define(&$symbol) {
20    if ($token = $this->definitions[$symbol->value] && $token->reserved) {
21      throw new Exception("Already defined: {$symbol->value}");
22    }
23
24    $this->definitions[$symbol->value] = $symbol;
25    $symbol->reserved = FALSE;
26    $symbol->nud = 'nud_itself';
27    $symbol->led = NULL;
28    $symbol->std = NULL;
29    $symbol->lbp = 0;
30    $symbol->scope = $this;
31    $symbol->global_scope = empty($this->_parent);
32
33    return $symbol;
34  }
35
36  /**
37   * Mark an assignment made in the current scope between two symbols
38   *
39   * @param Symbol $to_expression The expression $expression is assigned to
40   * @param Symbol $expression The expression being assigned
41   */
42  public function assignment($to_expression, $expression) {
43    // Only let through assignments to actual lookups (foo or foo.bar.baz)
44    // where the assignment is also a lookup, or an object (which may contain lookups)
45    if (is_object($to_expression) && $to_expression->is_lookup()) {
46      if ($this !== $to_expression->scope) {
47        // The assignment might be referencing a higher scope (e.g. without var)
48        return $to_expression->scope->assignment($to_expression, $expression);
49      }
50
51      $this->assignments[$to_expression->value] = array();
52
53      $expressions = array($expression);
54      if ($possibilities = $this->possibilities($expression)) {
55        $expressions = $possibilities;
56      }
57      foreach ($expressions as $expression) {
58        if (is_object($expression) && ($expression->is_lookup() || $expression->id == '{')) {
59          $this->assignments[$to_expression->value][] = $expression;
60        }
61      }
62    }
63  }
64
65  protected function possibilities($symbol, $possibilities=array()) {
66    $symbols = $symbol;
67    if (!is_array($symbols)) {
68      $symbols = array($symbols);
69    }
70    foreach ($symbols as $symbol) {
71      if (is_array($symbol)) {
72        $possibilities = $this->possibilities($symbol, $possibilities);
73      }
74      elseif ($symbol->is_option()) {
75        $firsts = $symbol->first;
76        if (!is_array($firsts)) {
77          $firsts = array($firsts);
78        }
79        foreach ($firsts as $first) {
80          if (is_array($first)) {
81            $possibilities = $this->possibilities($first, $possibilities);
82          }
83          elseif ($first->possible_variable()) {
84            $possibilities[] = $first;
85          }
86        }
87
88        $seconds = $symbol->second;
89        if (!is_array($seconds)) {
90          $seconds = array($seconds);
91        }
92        foreach ($seconds as $second) {
93          if (is_array($second) || $second->is_option()) {
94            $possibilities = $this->possibilities($second, $possibilities);
95          }
96          elseif ($second->possible_variable()) {
97            $possibilities[] = $second;
98          }
99        }
100      }
101    }
102    return $possibilities;
103  }
104
105  public function assigned($variable, $as_array=FALSE) {
106    if (isset($this->assignments[$variable])) {
107      return $as_array ? $this->assignments[$variable] : $this->assignments[$variable][0];
108    }
109    if (isset($this->parent)) {
110      return $this->_parent->assigned($variable, $as_array);
111    }
112  }
113
114  /**
115   * Sets the current scope's parent
116   *
117   * @param Scope $parent
118   */
119  public function setParent($parent) {
120    if ($parent instanceof Scope) {
121      return ($this->_parent = $parent);
122    }
123  }
124
125  /**
126   * Returns the current parent
127   */
128  public function parent() {
129    // This is how pop() will work as well
130    return $this->_parent;
131  }
132
133  public function definition($name) {
134    return $this->definitions[$name];
135  }
136
137  /**
138   * Tries to look up through each scope
139   * to find a symbol with the same name
140   * and returns the global symbol or empty
141   * (name) symbol instead
142   */
143  public function find ($name, $symbol_table) {
144    if ($symbol_table[$name]) {
145      return clone $symbol_table[$name];
146    }
147
148    $scope = $this;
149    while (1) {
150      if ($symbol = $scope->definition($name)) {
151        return clone $symbol;
152      }
153      if (!$scope->parent()) {
154        if (array_key_exists($name, $symbol_table)) {
155          return $symbol_table[$name];
156        }
157        $symbol = $symbol_table['(name)'];
158        $s = clone $symbol;
159        $s->global_scope = TRUE;
160        $s->reserved = FALSE;
161        $s->nud = 'nud_itself';
162        $s->led = NULL;
163        $s->std = NULL;
164        $s->lbp = 0;
165        $s->scope = $scope;
166        return $s;
167      }
168      $scope = $scope->parent();
169    }
170  }
171
172  /**
173   * Marks a variable symbol as being reserved in the current scope
174   *
175   * @param Symbol @symbol The variable symbol to mark reserved
176   */
177  public function reserve($symbol) {
178    if ($symbol->arity != 'name' || $symbol->reserved) {
179      return;
180    }
181
182    if ($token = $this->definitions[$symbol->value]) {
183      if ($token->reserved) {
184        $symbol->reserved = TRUE;
185        if (!$this->parent()) {
186          $symbol->global_scope = TRUE;
187        }
188        return;
189      }
190      if ($token->arity == 'name') {
191        throw new Exception("Already defined: {$symbol->value}");
192      }
193    }
194
195    $symbol->reserved = TRUE;
196    if (!$this->parent()) {
197      $symbol->global_scope = TRUE;
198    }
199    $this->definitions[$symbol->value] = $symbol;
200  }
201}
Note: See TracBrowser for help on using the repository browser.