-
Notifications
You must be signed in to change notification settings - Fork 1
/
parseRecordLabel.yp
129 lines (94 loc) · 2.43 KB
/
parseRecordLabel.yp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#
# parseRecordLabel.yp
#
#
#
# Parse::Yapp grammar file. Used to create parser for the record node
# labels
#
%token <i> T_string
%left '{'
%%
rlabel : field optMoreFields
{
shift;
my ($arg1, $arg2) = @_;
my (@arg1, @arg2);
# flatten any args
if( ref($arg1) eq 'ARRAY' ){
@arg1 = @$arg1;
}
else{
@arg1 = ($arg1);
}
if( ref($arg2) eq 'ARRAY' ){
@arg2 = @$arg2;
}
elsif(defined($arg2)){
@arg2 = ($arg2);
}
return [ @arg1, @arg2 ];
}
| /* empty */
;
optMoreFields : '|' rlabel { #print "rlabel = ".Data::Dumper::Dumper($_[2])." in optMoreFields\n";
return $_[2]; }
| /* empty */
;
field : boxlabel { return $_[1]; }
| '{' rlabel '}' { return $_[2]; }
;
boxlabel : optName T_string { return { $_[1] || '', $_[2] } ; }
;
optName : '<' T_string '>' { return $_[2] }
| /* empty */
;
%%
sub Error {
my $parse = shift;
my($token)=$parse->YYCurtok;
my($value)=$parse->YYCurval;
my($expected)=$parse->YYExpect;
my $input = $parse->YYData->{INPUT};
# Get rid of all but the first line
($input) = split("\n",$input);
print "Parse Error, Got token/value '$token', '$value'; Expected token '$expected'\n";
print "Near line :\n".$input."\n";
exit(1);
}
sub Lexer {
my($parser)=shift;
my @expect = $parser->YYExpect;
# If at the end of the string, and expecting a T_string token
# Return a null t_string
# This enables strings like '<f0> 0x10ba8| <f1>' to be parsed
# correctly
if( $parser->YYData->{INPUT} eq '' && @expect == 1 && $expect[0] eq 'T_string'){
return('T_string','');
}
defined($parser->YYData->{INPUT})
or return('',undef);
for( $parser->YYData->{INPUT}){
# Differnt Token Types
# check for tokens '<>{} tokens (Whitespace OK)
if( s/^\s*([\<\>\{])//){ # <, > and { with whitespace before
return($1, $1);
}
if( s/^(\})\s*//){ # } with whitespace after
return($1, $1);
}
if( s/^(\|)//){ # | with no whitespace
return($1, $1);
}
# T_string
s/^(.*?)((?<!\\)[\>\{\|\}])/$2/s # strings with embedded special characters (not backslashed)
and return('T_string',$1);
# End of string, return everything
s/(.+)//s
and return ('T_string', $1);
# Other stuff
s/^(.)//s
and return($1,$1);
return('','');
}
}