%%prioritized from top to bottom
<!--.*--> := comment
<\?.*?> := version
</.*?> := end
<.*?/ > := sigton
<.*> := begin
:= value
接着,需要定义yacc的语法文件xml.yacc:
%yacc%
%%prioritized from bottom to top
xml := version EOF { Xml_Version }
| version pair EOF { Xml_VersionPair }
pair := pair pair { Pair_PairPair }
pair := begin end { Pair_BeginEnd }
| begin value end { Pair_BeginValueEnd }
| begin pair end { Pair_BeginPairEnd }
| begin value pairs end { Pair_BeginValuePairEnd }
| sigton { Pair_Sigton }
| comment { Pair_Comment }
%code%
package xml;
use strict;
use warnings;
sub _XmlAlarmMock
{
print @_;
}
sub _XmlDebugMock
{
my $debugInfo = shift;
#print "$debugInfo\n";
sub _printMock{print @_;};
#&zDebug::DataDump(\&_printMock, \@_);
}
sub _XmlCheckNode
{
my $refNode = shift;
if($refNode->{BEGIN})
{
my $begin = $refNode->{BEGIN}->{TEXT};
my $end = $refNode->{END}->{TEXT};
printf("##### check node $begin, $end.\n");
$begin =~ /^<([a-zA-Z_0-9]+)/;
my $a = $1;
$end =~ /^<\/([a-zA-Z_0-9]+)/;
my $b = $1;
if($a ne $b)
{
&zDebug::DataDump(\&_XmlAlarmMock, $refNode);
&zDebug::DataDump(\&_XmlAlarmMock, $refNode->{BEGIN});
&zDebug::DataDump(\&_XmlAlarmMock, $refNode->{END});
my $line = $refNode->{BEGIN}->{LINE};
print "\nBEGIN <$a> at LINE [$line] missing END!!!\n";
exit(0);
}
}
=pod
if($refNode->{VALUE})
{
my $value = $refNode->{VALUE}->{TEXT};
if($value =~ /[<>]/)
{
&zDebug::DataDump(\&_XmlAlarmMock, $refNode);
&zDebug::DataDump(\&_XmlAlarmMock, $refNode->{VALUE});
print "\nVALUE contains <>!!!\n";
exit(0);
}
}
=cut
}
sub _XmlCheckValue
{
my $refNode = shift;
}
sub Xml_Version
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my @pair;
my %xml = (VERSION=>$params[0], PAIR=>\@pair);
return \%xml;
}
sub Xml_VersionPair
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %xml = (VERSION=>$params[0], PAIR=>$params[1]);
return $params[0];
}
sub Pair_BeginEnd
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %node;
$node{BEGIN} = $params[0];
$node{END} = $params[1];
&_XmlCheckNode(\%node);
my @pair = (\%node,);
return \@pair;
}
sub Pair_BeginValueEnd
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %node;
$node{BEGIN} = $params[0];
$node{VALUE} = $params[1];
$node{END} = $params[2];
&_XmlCheckNode(\%node);
my @pair = (\%node,);
return \@pair;
}
sub Pair_Sigton
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %node;
$node{SIGTON} = $params[0];
my @pair = ($params[0],);
return \@pair;
}
sub Pair_Comment
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %node;
$node{COMMENT} = $params[0];
my @pair = (\%node,);
return \@pair;
}
sub Pair_BeginPairEnd
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %node;
$node{BEGIN} = $params[0];
$node{PAIR} = $params[1];
$node{END} = $params[2];
&_XmlCheckNode(\%node);
my @pair = (\%node,);
return \@pair;
}
sub Pair_BeginValuePairEnd
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
my %node;
$node{BEGIN} = $params[0];
$node{VALUE} = $params[1];
$node{PAIR} = $params[2];
$node{END} = $params[3];
&_XmlCheckNode(\%node);
my @pair = (\%node,);
return \@pair;
}
sub Pair_PairPair
{
my @params = @_;
&_XmlDebugMock(&zError::FunName().' ['.&zError::FileLine().']', \@_);
push @{$params[0]}, @{$params[1]};
return $params[0];
}
View Code 最后是应用程序部分p_xml.pl:
#/usr/bin/perl
use strict;
use warnings;
use zFile;
use zTrace;
use zError;
use zDebug;
use zLex;
use zLex;
use zYacc;
sub main
{
my $lex = zLex->New(@ARGV);
$lex->SetupFile('xml.lex');
#$lex->PrintDocLex();
my $yacc = zYacc->New(@ARGV);
$yacc->SetupFile('xml.yacc');
$yacc->SaveCode('xml.pm');
#$yacc->ImportCode('xml', 'xml');
$yacc->PrintGrammarTree();
$yacc->PrintConflictTree();
my $text = $lex->ParserFile('sample0.xml');
&DataDump(\&TraceDebug, $text);
my @re = $yacc->Compile($text);
&DataDump(undef, \@re);
}
&main();
View Code 样例只做了xml到内存数据结构的解析。
测试用xml文件sample0.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!--Settings for MSP-->
<Config>
<tag1> value1 </tag1>
< Single Node / >
</Config>