include
'ttrie.php'
;<br><br>
class
Rule
extends
TTrie {<br>
public
$rule
=
array
();<br>
public
$savematch
= 0;<br><br>
function
__construct(
$s
=
''
) {<br>
$this
->set(
array
(<br>
' '
=>
'Separated'
,<br>
"\r\n"
=>
'set_rule'
,<br>
"\n"
=>
'set_rule'
,<br>
"\t"
=>
'Separated'
,<br>
'->'
=>
'Separated'
,<br>
'→'
=>
'Separated'
,<br>
'|'
=>
'set_parallel_rule'
,<br> ));<br>
$this
->match(
$s
);<br>
if
(
$this
->rule[0][0] ==
$this
->rule[0][1]) {<br>
if
(
count
(
$this
->rule[0]) == 2)
$this
->rule[0][0] .=
"'"
;<br>
else
array_unshift
(
$this
->rule,
array
(
$this
->rule[0][0].
"'"
,
$this
->rule[0][0]));<br> }
else
{<br>
$c
=
$this
->rule[0][0];<br>
$n
= 0;<br>
foreach
(
$this
->rule
as
$r
)
if
(
$r
[0] ==
$c
)
$n
++;<br>
if
(
$n
> 1)
array_unshift
(
$this
->rule,
array
(
$this
->rule[0][0].
"'"
,
$this
->rule[0][0]));<br> }<br> }<br>
function
Separated() {<br> }<br>
function
set_rule() {<br>
$this
->rule[] =
$this
->buffer;<br>
$this
->buffer =
array
();<br> }<br>
function
set_parallel_rule() {<br>
$t
=
$this
->buffer[0];<br>
$this
->set_rule();<br>
$this
->buffer[] =
$t
;<br> }<br>}<br><br><br>
class
Grammar {<br>
var
$closure
=
array
();<br>
var
$first
=
array
();<br>
var
$follow
=
array
();<br>
var
$rule
=
array
();<br>
var
$identifier
=
array
();<br>
var
$leay
=
array
();<br>
var
$forecast
=
array
();<br>
var
$stack
=
array
();<br>
var
$ll
= 'LL(0)
';<br> var $lr = '
LR(0)
';<br><br> function __construct($s='
') {<br> $p = new Rule($s);<br> $this->rule = $p->rule;<br> $this->set_grammar();<br> }<br><br> function set_grammar() {<br> foreach($this->rule as $rule) {<br> if(! in_array($rule[0], $this->identifier)) $this->identifier[] = $rule[0];<br> }<br> foreach($this->rule as $rule) {<br> foreach($rule as $v)<br> if(! in_array($v, $this->identifier) && ! in_array($v, $this->leay))<br> $this->leay[] = $v;<br> }<br> $this->set_first();<br> $this->set_follow();<br> $this->set_closure();<br> $this->set_select();<br> $this->set_forecast();<br> }<br> function set_first() {<br> foreach($this->rule as $rule) $this->first[$rule[0]] = array();<br> //直接收取 形如U->a…的产生式(其中a是终结符),把a收入到First(U)中<br> foreach($this->rule as $v) {<br> if(in_array($v[1], $this->leay)) $this->first[$v[0]][] = $v[1];<br> }<br> //反复传递 形入U->P1P2P3…Pn的产生式(其中P是非终结符),应先把First(P1)中的全部内容传送到First(U)中,如果P1中有ε,把First(P2)中的内容传送到First(U)中,类推直到Pi中无ε<br> do {<br> $t = serialize($this->first);<br> foreach($this->rule as $rule) {<br> for($i=1; $i<count></count> $v = $rule[$i];<br> if(in_array($v, $this->identifier)) {<br> $this->first[$rule[0]] = array_unique(array_merge($this->first[$rule[0]], $this->first[$v]));<br> if(! in_array('
#
', $this->first[$v])) break;<br> }else break;<br> }<br> }<br> }while($t != serialize($this->first));<br> }<br> function set_follow() {<br> foreach($this->rule as $rule) $this->follow[$rule[0]] = array();<br> //直接收取 形如 …Ua… 的,把a直接收入到Follow(U)中<br> foreach($this->rule as $rule) {<br> for($i=1; $i<count></count> if(in_array($rule[$i], $this->identifier) && in_array($rule[$i+1], $this->leay))<br> $this->follow[$rule[$i]][] = $rule[$i+1];<br> }<br> if(in_array($rule[$i], $this->identifier)) $this->follow[$rule[$i]][] = '
#
';<br> }<br> foreach($this->follow as &$v) if(! $v) $v[] = '
#
';<br> //直接收取 形如 …UP…(P是非终结符)的,把First(P)中非ε收入到Follow(U)中<br> foreach($this->rule as $rule) {<br> for($i=1; $i<count></count> if(in_array($rule[$i], $this->identifier) && in_array($rule[$i+1], $this->identifier)) {<br> $this->follow[$rule[$i]] = array_unique(array_merge($this->follow[$rule[$i]], array_diff($this->first[$rule[$i+1]], array('
#'))));<br> }<br> }<br> }<br> //反复传递 形如U->aP的(P是非终结符)或U->aPQ(P,Q为非终结符且Q中含ε),应把Follow(U)中的全部内容传送到Follow(P)中<br>
do
{<br>
$t
= serialize(
$this
->follow);<br>
foreach
(
$this
->rule
as
$rule
) {<br>
$s
=
$rule
[0];<br>
$d
=
end
(
$rule
);<br>
if
(in_array(
$d
,
$this
->leay))
continue
;<div
class
=
"clear"
>
</div>