diff --git a/src/Makefile.in b/src/Makefile.in index afffc0bb2..b7db98f5b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -88,7 +88,6 @@ clean mostlyclean distclean maintainer-clean:: -rm -rf obj_* *.log *.dmp *.vpd core -rm -f *.o *.d perlxsi.c *_gen_* -rm -f *__gen* - -rm -f *.yy.* y.output y.tab.[cho] *_test -rm -f .objcache* distclean maintainer-clean:: diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index fa8075fe0..8176e2e1b 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -118,7 +118,6 @@ make_info: clean mostlyclean distclean maintainer-clean:: -rm -f *.o *.d perlxsi.c *_gen_* -rm -f *__gen* - -rm -f *.yy.* y.output y.tab.[cho] *_test -rm -f obj_* .objcache* distclean maintainer-clean:: clean @@ -245,10 +244,10 @@ V3Number_test: V3Number_test.o %.o: %.c $(OBJCACHE) ${CC} ${CPPFLAGS} -c $< -V3Read.o: V3Read.cpp V3Lexer.yy.cpp +V3Read.o: V3Read.cpp V3Lexer.yy.cpp V3ParseBison.c $(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< -V3Parse.o: V3Parse.cpp y.tab.c +V3Parse.o: V3Parse.cpp V3ParseBison.c $(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp @@ -257,19 +256,19 @@ V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp #### Generated files # Target rule called before parallel build to make generated files -serial:: V3Ast__gen_classes.h y.tab.c +serial:: V3Ast__gen_classes.h V3ParseBison.c V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h $(PERL) $(ASTGEN) -I$(srcdir) --classes -y.tab.h: y.tab.c +V3ParseBison.h: V3ParseBison.c # Have only one output file in this rule to prevent parallel make issues -y.tab.c: verilog.y $(HEADERS) bisonpre +V3ParseBison.c: verilog.y $(HEADERS) bisonpre @echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer." - $(PERL) $(BISONPRE) --yacc ${YACC} -d -v -o y.tab.c $< + $(PERL) $(BISONPRE) --yacc ${YACC} -d -v -o V3ParseBison.c $< -V3Lexer_pregen.yy.cpp: verilog.l y.tab.h $(HEADERS) +V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS) ${LEX} --version ${LEX} ${LFLAGS} -o$@ $< diff --git a/src/V3Parse.cpp b/src/V3Parse.cpp index 8b32440cd..89bf01787 100644 --- a/src/V3Parse.cpp +++ b/src/V3Parse.cpp @@ -19,8 +19,8 @@ // //************************************************************************* -#include "V3Ast.h" // This must be before yy.tab.c, as we don't want #defines to conflict +#include "V3Ast.h" // This must be before V3ParseBison.cpp, as we don't want #defines to conflict //====================================================================== -// The guts are in bison -#include "y.tab.c" +// The guts came from bison +#include "V3ParseBison.c" diff --git a/src/bisonpre b/src/bisonpre index 3778d38ba..61878e854 100755 --- a/src/bisonpre +++ b/src/bisonpre @@ -9,7 +9,9 @@ use Pod::Usage; use strict; use vars qw ($Debug $VERSION); -$VERSION = '3.101'; +$VERSION = '3.202'; + +our $Self; #====================================================================== # main @@ -74,13 +76,17 @@ sub process { clean_input($Opt_Input, tmp_prefix().".y"); + my $supports_report = (bison_version_check() >= 2.3); + # Run bison my $command = ($Opt_Yacc .($Opt_Debug?" -t":"") .($Opt_Definitions?" -d":"") .($Opt_Token_Table?" -k":"") - .($Opt_Name_Prefix?" -p $Opt_Name_Prefix":"") .($Opt_Verbose?" -v":"") + .(($Opt_Verbose && $supports_report)?" --report=itemset --report=lookahead":"") + # -p required for GLR parsers; they write to -p basename, not -o + .($Opt_Name_Prefix?" -p $Opt_Name_Prefix":"") ." -b ".tmp_prefix() ." -o ".tmp_prefix().".c" ." ".tmp_prefix().".y" ); @@ -94,16 +100,16 @@ sub process { die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n"; } - clean_output(tmp_prefix().".output",output_prefix().".output"); + clean_output(tmp_prefix().".output",output_prefix().".output", 1); warning_check(output_prefix().".output"); - clean_output(tmp_prefix().".c", output_prefix().".c"); - clean_output(tmp_prefix().".h", output_prefix().".h"); + clean_output(tmp_prefix().".c", output_prefix().".c", 0); + clean_output(tmp_prefix().".h", output_prefix().".h", 0); remove_tmp(); } sub tmp_prefix { - return output_prefix().".pre"; + return output_prefix()."_pretmp"; } sub output_prefix { @@ -143,22 +149,44 @@ sub bison_version_check { sub clean_output { my $filename = shift; my $outname = shift || $filename; + my $is_output = shift; print " edit $filename $outname\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my @lines = $fh->getlines; $fh->close; - (my $basename = tmp_prefix().".y") =~ s!.*/!!; + (my $basename = tmp_prefix()) =~ s!.*/!!; $basename = quotemeta($basename); - (my $newbase = output_prefix().".y") =~ s!.*/!!; + (my $newbase = output_prefix()) =~ s!.*/!!; + + if ($is_output) { + my %state_line; my $l=0; + foreach my $line (@lines) { + $l++; + $state_line{$1} = $l if $line =~ /^state (\d+)\s*$/; + } + my @out; + foreach my $line (@lines) { + $state_line{$1} = $l if $line =~ /^state (\d+)\s*$/; + if ($line =~ /^State (\d+) (conflicts)/) { + chomp $line; + $line .= " // line $state_line{$1}" if $state_line{$1}; + $line .= "\n"; + } + push @out, $line; + } + @lines = @out; @out = (); + } $fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n"; foreach my $line (@lines) { - # Fix bison 2.3 and GCC 4.2.1 - $line =~ s!\(YY_\("!(YY_((char*)"!g; # Fix filename refs $line =~ s!$basename!$newbase!g; + # Fix bison 2.3 and GCC 4.2.1 + $line =~ s!\(YY_\("!(YY_((char*)"!g; + # Fix bison 2.3 glr-parser warning about yyerrorloc.YYTYPE::yydummy uninit + $line =~ s!(YYLTYPE yyerrloc;)!$1 yyerrloc.yydummy=0;/*bisonpre*/!g; $fh->write($line); } $fh->close; @@ -169,8 +197,7 @@ sub warning_check { my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; while (defined(my $line = $fh->getline)) { - if ($line =~ /(conflicts|warning:)/) { - clean_output(); + if ($line =~ /(conflicts|warning:|^useless)/i) { die "%Error: $filename:$.: $line\n"; } } @@ -189,17 +216,67 @@ sub clean_input { $fh->close; # Find "%tokens:" + # Find "rule:" and replace with just "rule:" + my %types; + my %rules; $Self->{rules} = \%rules; my %tokens; - foreach my $line (@lines) { - if ($line =~ /^%token\s*<(\S+)>\s*(\S+)/) { - $tokens{$2} = $1; + my $last_rule; + my $section = 1; + { + my @linesin = @lines; @lines=(); my $l=0; + foreach my $line (@linesin) { + $l++; + # ^/ to prevent comments from matching + $line =~ m!^[a-zA-Z0-9_<>]+:[^/]*[a-zA-Z]! and die "%Error: $filename:$l: Move text on rule line to next line: $line\n"; + if ($line =~ /^%%/) { + $section++; + if ($section==2) { $last_rule = undef; } + } + elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S+)>:/$1:/) { + !$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n"; + $types{$2}{$1} = 1; + $rules{$1}{name} = $1; + $rules{$1}{type} = $2; + !$last_rule or die "%Error: $filename:$l: Unterminated previous rule\n"; + $last_rule = $1; + } elsif ($line =~ /^([a-zA-Z0-9_]+):/) { + !$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n"; + $rules{$1}{name} = $1; + $rules{$1}{type} = ""; + !$last_rule or die "%Error: $filename:$l: Unterminated previous rule\n"; + $last_rule = $1; + } + push @lines, $line; + # Now clean the line and extract some more info + (my $cline = $line) =~ s/\/\/.*$/\n/; + (my $rline = $line) =~ s/\/\/.*$/\n/; + if ($cline =~ /^\s*;/) { + $last_rule or die "%Error: $filename:$l: Stray semicolon\n"; + $last_rule = undef; + } elsif ($last_rule) { + $rules{$last_rule}{rules_and_productions} .= $cline; + } + if ($cline =~ /^%token\s*<(\S+)>\s*(\S+)/) { + !$tokens{$2} or die "%Error: $filename:$l: Redeclaring '$2': $line\n"; + $tokens{$2} = $1; + } + foreach my $tok (split /[^a-zA-Z0-9_]+/, $cline) { + if ($last_rule && $tok=~/^[a-zA-Z]/) { + #print "TT $last_rule $tok\n"; + $rules{$last_rule}{subrules}{$tok} = 1; + $rules{$tok}{parentrules}{$last_rule} = 1; + } + } } } + #use Data::Dumper; print Dumper(\%rules); + # Replace BISONPRE_NOT(type,...) with expanded list { my @linesin = @lines; @lines=(); my $l=0; foreach my $line (@linesin) { + $l++; if ($line =~ /BISONPRE_NOT/) { ($line =~ s/BISONPRE_NOT\((\S+)\)\s*({[^}]+})\s*$//) or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n"; @@ -225,19 +302,40 @@ sub clean_input { } } - # Find "rule:" and replace with just "rule:" - my %types; + # Replace BISONPRE_COPY(type,{code}) { my @linesin = @lines; @lines=(); my $l=0; foreach my $line (@linesin) { - # ^/ to prevent comments from matching - if ($line =~ s/^([^<\/ \t\n]+)<(\S+)>:/$1:/) { - $types{$2}{$1} = 1; + $l++; + if ($line =~ /BISONPRE_COPY/) { + ($line =~ s/BISONPRE_COPY\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/) + or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n"; + my $rule = $1; my $code = $2; + $rules{$rule} or die "%Error: $filename:$l: Can't find definition for rule: $rule\n"; + # Push it all onto one line to avoid error messages changing + my $insert = $rules{$rule}{rules_and_productions}; + $insert =~ s/^\S+://g; # Strip rule name + #print "COPY code $code\n"; + #print "COPY in $insert\n"; + $_=$insert; eval("$code; \$_;"); $insert = $_; + #print "COPY out $insert\n"; + while ($insert =~ s/[ \t\n]+\n/\n/go) {} + $line =~ s/{HERE}/$insert/; } push @lines, $line; } } + # Replace ~[x]~ - must be after BISONPRE_COPY expansion + { + my @linesin = @lines; @lines=(); my $l=0; + foreach my $line (@linesin) { + $l++; + $line =~ s/~[a-zA-Z0-9_]+~//g; + push @lines, $line; + } + } + # Find "BISONPRE_TYPES" { my @linesin = @lines; @lines=(); my $l=0; @@ -273,7 +371,6 @@ sub clean_input { $fh->close; } - ####################################################################### __END__ @@ -303,11 +400,21 @@ various compile warnings. This is expanded into %type declarations. +=item ~[a-z]+~ + +Any text matching ~[a-z]+~ is removed. This allows optional text to be +used only when the rule containing the ~~ is used in a BISONPRE_COPY. + =item rule_label: This allows the label declaring a rule to also specify the type of the rule. The type will be inserted where /*BISONPRE_TYPES*/ is encountered. +=item BISONPRE_COPY(rule, {code}) + +Copy the rules and productions from the specified rule, filter through the +Perl code provided in the {} and insert here into the output file. + =item BISONPRE_NOT(token[, token...]) Create a rule that matches every token except for those specified. @@ -351,16 +458,6 @@ This switch causes the name.tab.c output to include a list of token names in order by their token numbers; this is defined in the array yytname. Also generated are #defines for YYNTOKENS, YYNNTS, YYNRULES, and YYNSTATES. -=item -p prefix -=item --name-prefix=prefix - -Passed to bison. - -Rename the external symbols used in the parser so that they start with -prefix instead of yy. The precise list of symbols renamed is yyparse, -yylex, yyerror, yylval, yychar, and yydebug. For example, if you use -p c, -the names become cparse, clex, and so on. - ==item -t ==item --debug diff --git a/src/verilog.l b/src/verilog.l index 5c77b3eed..ca486d83b 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -27,7 +27,7 @@ #include #include "V3Read.h" #include "V3Number.h" -#include "y.tab.h" +#include "V3ParseBison.h" // Generated by bison extern void yyerror(char*); extern void yyerrorf(const char* format, ...); diff --git a/src/verilog.y b/src/verilog.y index 23e9ad930..3dd660ef6 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -593,13 +593,17 @@ net_type: // ==IEEE: net_type | yWIRE { VARDECL(WIRE); } | yTRI { VARDECL(TRIWIRE); } ; -varGParam: yPARAMETER { VARDECL(GPARAM); } +varGParam: + yPARAMETER { VARDECL(GPARAM); } ; -varLParam: yLOCALPARAM { VARDECL(LPARAM); } +varLParam: + yLOCALPARAM { VARDECL(LPARAM); } ; -varGenVar: yGENVAR { VARDECL(GENVAR); } +varGenVar: + yGENVAR { VARDECL(GENVAR); } ; -varReg: yREG { VARDECL(REG); } +varReg: + yREG { VARDECL(REG); } | yINTEGER { VARDECL(INTEGER); } ; @@ -1390,33 +1394,47 @@ gatePulldownList: | gatePulldownList ',' gatePulldown { $$ = $1->addNext($3); } ; -gateBuf: gateIdE instRangeE '(' varRefDotBit ',' expr ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } +gateBuf: + gateIdE instRangeE '(' varRefDotBit ',' expr ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } ; -gateBufif0: gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), $6)); } +gateBufif0: + gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), $6)); } ; -gateBufif1: gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, $6, new AstConst($3,V3Number($3,"1'bz")))); } +gateBufif1: + gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, $6, new AstConst($3,V3Number($3,"1'bz")))); } ; -gateNot: gateIdE instRangeE '(' varRefDotBit ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } +gateNot: + gateIdE instRangeE '(' varRefDotBit ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } ; -gateNotif0: gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), new AstNot($3, $6))); } +gateNotif0: + gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstConst($3,V3Number($3,"1'bz")), new AstNot($3, $6))); } ; -gateNotif1: gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstNot($3,$6), new AstConst($3,V3Number($3,"1'bz")))); } +gateNotif1: + gateIdE instRangeE '(' varRefDotBit ',' expr ',' expr ')' { $$ = new AstAssignW ($3,$4,new AstCond($3,$8, new AstNot($3,$6), new AstConst($3,V3Number($3,"1'bz")))); } ; -gateAnd: gateIdE instRangeE '(' varRefDotBit ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } +gateAnd: + gateIdE instRangeE '(' varRefDotBit ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } ; -gateNand: gateIdE instRangeE '(' varRefDotBit ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } +gateNand: + gateIdE instRangeE '(' varRefDotBit ',' gateAndPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } ; -gateOr: gateIdE instRangeE '(' varRefDotBit ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } +gateOr: + gateIdE instRangeE '(' varRefDotBit ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } ; -gateNor: gateIdE instRangeE '(' varRefDotBit ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } +gateNor: + gateIdE instRangeE '(' varRefDotBit ',' gateOrPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } ; -gateXor: gateIdE instRangeE '(' varRefDotBit ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } +gateXor: + gateIdE instRangeE '(' varRefDotBit ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,$6); $$->allowImplicit(true); } ; -gateXnor: gateIdE instRangeE '(' varRefDotBit ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } +gateXnor: + gateIdE instRangeE '(' varRefDotBit ',' gateXorPinList ')' { $$ = new AstAssignW ($3,$4,new AstNot($5,$6)); $$->allowImplicit(true); } ; -gatePullup: gateIdE instRangeE '(' varRefDotBit ')' { $$ = new AstPull ($3, $4, true); } +gatePullup: + gateIdE instRangeE '(' varRefDotBit ')' { $$ = new AstPull ($3, $4, true); } ; -gatePulldown: gateIdE instRangeE '(' varRefDotBit ')' { $$ = new AstPull ($3, $4, false); } +gatePulldown: + gateIdE instRangeE '(' varRefDotBit ')' { $$ = new AstPull ($3, $4, false); } ; gateIdE: /*empty*/ {}