pl_proto.pl 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;
  5. my $SOURCE_FILE = $ARGV[0];
  6. sub read_to_var($) {
  7. my $file_path = shift;
  8. my $content;
  9. open(my $fh, '<', $file_path) or die "cannot open file $file_path";
  10. {
  11. local $/;
  12. $content = <$fh>;
  13. }
  14. close($fh);
  15. return $content;
  16. }
  17. my $src_content = read_to_var($SOURCE_FILE);
  18. sub trim($) {
  19. my $str = shift;
  20. $str =~ s/^\s+|\s+$//g;
  21. return $str;
  22. }
  23. my @module_library_paths = (
  24. ".",
  25. );
  26. my %modules;
  27. sub parse_module_file {
  28. my $src = shift;
  29. my %module;
  30. my $last_proc_type = "null";
  31. my $last_input = "null";
  32. my $last_output = "null";
  33. foreach my $line ( split("\n", $src) ) {
  34. chomp $line;
  35. if ( $line =~ m/^#/ ) {
  36. next;
  37. }
  38. if ( $line =~ m/^Manufacturer:(.*)/ ) {
  39. my $manu = $1;
  40. $manu = trim($manu);
  41. $module{'Manufacturer'} = $manu;
  42. }
  43. if ( $line =~ m/^Module:(.*)/ ) {
  44. my $mod = $1;
  45. $mod = trim($mod);
  46. $module{'Module'} = $mod;
  47. }
  48. if ( $line =~ m/^Revision:(.*)/ ) {
  49. my $rev = $1;
  50. $rev = trim($rev);
  51. $module{'Rev'} = $rev;
  52. }
  53. if ( $line =~ m/^-\ / ) {
  54. if ( $line =~ m/^-\ Input:(.*)/ ) {
  55. my $input = $1;
  56. $input = trim($input);
  57. my %input_chars;
  58. $last_input = $input;
  59. $last_proc_type = "input";
  60. $module{'Inputs'}->{$input} = \%input_chars;
  61. }
  62. if ( $line =~ m/^-\ Knob:(.*)/ ) {
  63. my $knob = $1;
  64. $knob = trim($knob);
  65. my %knob_chars;
  66. $last_input = $knob;
  67. $last_proc_type = "input";
  68. $module{'Inputs'}->{$knob} = \%knob_chars;
  69. }
  70. if ( $line =~ m/^-\ Output:(.*)/ ) {
  71. my $output = $1;
  72. $output = trim($output);
  73. my %output_chars;
  74. $last_output = $output;
  75. $last_proc_type = "output";
  76. $module{'Outputs'}->{$output} = \%output_chars;
  77. }
  78. }
  79. if ( $line =~ m/^--\ / ) {
  80. if ( $line =~ m/^--\ Position:(.*)/ ) {
  81. my $pos_args = $1;
  82. $pos_args = trim($pos_args);
  83. if ( $last_proc_type eq "input" ) {
  84. $module{'Inputs'}->{$last_input}->{'pos'} = $pos_args;
  85. } elsif ( $last_proc_type eq "output" ) {
  86. $module{'Outputs'}->{$last_output}->{'pos'} = $pos_args;
  87. }
  88. }
  89. }
  90. }
  91. return \%module;
  92. }
  93. my %AST;
  94. my %PARSE_TABLE = (
  95. 'comment' => '^#.*$',
  96. 'title' => '^Title: (.*)$',
  97. 'mod_path' => '^ModuleDir\ "(.*)"$',
  98. 'import' => '^import (Module)::([a-zA-Z0-9]{1,})::([a-zA-Z0-9]{1,})(.*$)',
  99. 'set' => '^set\ (.*)$',
  100. );
  101. my %PARSE_RULES = (
  102. 'comment' => sub {},
  103. 'title' => sub {
  104. my $title = shift;
  105. $AST{'Title'} = $title;
  106. },
  107. 'mod_path' => sub {
  108. my $file_path = shift;
  109. if ( ! -d $file_path ) {
  110. die "Path: $file_path doesn't look like a directory, exiting";
  111. }
  112. push(@module_library_paths, $file_path);
  113. },
  114. 'import' => sub {
  115. my $module_path = shift;
  116. my @module_files = sub {
  117. my @files;
  118. foreach my $path ( @module_library_paths ) {
  119. my @f = split("\n", `find $path`);
  120. foreach my $file ( @f ) {
  121. if ( $file =~ m/.module$/ ) {
  122. push(@files, $file);
  123. }
  124. }
  125. }
  126. return @files;
  127. }->();
  128. foreach my $mod_file ( @module_files ) {
  129. my $mod_file_content = read_to_var($mod_file);
  130. my $mod_ref = parse_module_file($mod_file_content);
  131. foreach my $ref ( @{$AST{'Modules'}} ) {
  132. if ( $$mod_ref{'Manufacturer'} eq $$ref{'Manufacturer'} &&
  133. $$mod_ref{'Rev'} eq $$ref{'Rev'} ) {
  134. # We've already imported this module
  135. next;
  136. } else {
  137. push(@{$AST{'Modules'}}, $mod_ref);
  138. }
  139. }
  140. }
  141. },
  142. 'set' => sub { print("$_[0]\n"); },
  143. );
  144. # Basic line parser
  145. sub line_parse($) {
  146. my $line = shift;
  147. my $line_type = "null";
  148. my @line_caps;
  149. foreach my $key ( keys %PARSE_TABLE ) {
  150. if ( $line =~ m/$PARSE_TABLE{$key}/ ) {
  151. $line_type = $key;
  152. }
  153. }
  154. if ( $line_type ne "null" && $line =~ m/$PARSE_TABLE{$line_type}/) {
  155. if ( defined $1 ) {
  156. $PARSE_RULES{$line_type}->($1);
  157. } else {
  158. $PARSE_RULES{$line_type}->();
  159. }
  160. } else {
  161. print("$line\n");
  162. }
  163. }
  164. foreach my $line ( split("\n", $src_content) ) {
  165. chomp $line;
  166. if ( $line eq "" ) {
  167. next;
  168. }
  169. line_parse($line);
  170. }
  171. print Dumper %AST;