File: parser.pl

package info (click to toggle)
libconvert-binary-c-perl 0.85-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 13,260 kB
  • sloc: ansic: 47,820; perl: 4,980; yacc: 2,143; makefile: 61
file content (128 lines) | stat: -rw-r--r-- 2,748 bytes parent folder | download | duplicates (2)
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
################################################################################
#
# PROGRAM: parser.pl
#
################################################################################
#
# DESCRIPTION: Generate tokenizer code for C parser
#
################################################################################
#
# Copyright (c) 2002-2024 Marcus Holland-Moritz. All rights reserved.
# This program is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
#
################################################################################

use Devel::Tokenizer::C;

# keywords that cannot be disabled
@no_disable = qw(
  break
  case char continue
  default do
  else
  for
  goto
  if int
  return
  sizeof struct switch
  typedef
  union
  while
);

# keywords that can be disabled
@disable = qw(
  asm auto
  const
  double
  enum extern
  float
  inline
  long
  register restrict
  short signed static
  unsigned
  void volatile
);

@basic = qw(
  char
  double
  float
  int
  long
  short signed
  unsigned
);

# put them in a hash
@NDIS{@no_disable} = (1) x @no_disable;

$file = shift;

if( $file =~ /parser/ ) {
  $t = Devel::Tokenizer::C->new( TokenFunc => \&t_parser )
                          ->add_tokens( @disable, @no_disable );
}
elsif( $file =~ /basic/ ) {
  $t = Devel::Tokenizer::C->new( TokenFunc   => \&t_basic,
                                 TokenString => 'c',
                                 TokenEnd    => '*name',
                               )
                          ->add_tokens( @basic );
}
elsif( $file =~ /keywords/ ) {
  $t = Devel::Tokenizer::C->new( TokenFunc => \&t_keywords, TokenString => 'str' )
                          ->add_tokens( @disable );
}
elsif( $file =~ /ckeytok/ ) {
  $t = Devel::Tokenizer::C->new( TokenFunc => \&t_ckeytok, TokenString => 'name' )
                          ->add_tokens( @disable, @no_disable );
}
else { die "invalid file: $file\n" }

open OUT, ">$file" or die "$file: $!";
print OUT $t->generate;
close OUT;

sub t_parser {
  my $token = shift;
  if( exists $NDIS{$token} ) {
    return "return \U$token\E_TOK;\n";
  }
  else {
    return "if( pState->pCPC->keywords & HAS_KEYWORD_\U$token\E )\n"
         . "  return \U$token\E_TOK;\n";
  }
};

sub t_basic {
  my $token = shift;
  if( $token eq 'long' ) {
    return <<END
tflags |= tflags & T_LONG ? T_LONGLONG : T_LONG;
goto success;
END
  }
  return <<END
tflags |= T_\U$token\E;
goto success;
END
};

sub t_keywords {
  my $token = shift;
  return "keywords &= ~HAS_KEYWORD_\U$token\E;\n"
        ."goto success;\n";
};

sub t_ckeytok {
  my $token = shift;
  return <<END
static const CKeywordToken ckt = { \U$token\E_TOK, "$token" };
return &ckt;
END
};