3

Currently I'm linting our codebase. Some coding rules where defined at the beginning of the project, unfortunately not very much of them were used ;\

Is there an automatic way to refactor the code? For example ports that should be written in capital letters.

port_namePORT_NAME

I would rather use a more "intelligent" way like the refactoring for C/C++ in Eclipse which understands the code and does not only find and replace.

I'm using Sigasi, which has such a feature, but this feature does not scale very well, I have to chose each port by hand to start a refactor action. For thousands of ports this is a problem.

Is there a tool out there that runs on Windows 7 which is capable of something like that?

0

3 Answers 3

1

The Unix command line tools were made for this sort of thing. You don't necessarily need full syntax parsing if regexes can be made to fit your specific needs. If you can't get what you need using in-editor replacement as @Paebbels suggested then consider using Gnu sed. It is easiest to get on Windows by installing Cygwin or you can install one of the Msys ports.

Gnu sed has an extension that will uppercase a matched pattern and another that will in-place edit a file.

After matching the start of a port this script loops until no substitutions are made which indicates the end of the port:

# Capitalize formals in a port interface list
sed -i -e "/port *(/ {s/[^(;:]*:/\U&/g;: pdef;n;s/[^;:]*:/\U&/g;t pdef}" *.vhdl

This doesn't handle blank or comment lines in the port but additional match rules can be inserted to force a no-change substitution on them so that the loop doesn't terminate early.

If you want to capitalize the formals in an association list use the following:

sed -i -e "s/[[:alnum:]_]* *=>/\U&/g" *.vhdl

This will work for the most common case where the formal isn't wrapped in a function call.

If you need to capitalize all other places where these port names are used then you can produce a script that dumps out all the port formals as a new sed script. Then use that generated script to capitalize any word that matches.

sed -n -e "/port *(/ {s/[^(;:]*:/\U&/gp;: pdef;n;s/[^;:]*:/\U&/gp;t pdef}" foo.vhdl | \
sed -n -e "s/\([(,;]\)/\1\n/gp" | \
sed -n -e "s/ *\([[:alnum:]_]*\) *[:,].*/\1/p" | \
sed -e "s%\(.*\)%s/\1/\U\1\L/gi%" > foo_uc.sed

sed -i -f foo_uc.sed foo.vhdl
0

What about a smart editor, which can open multiple files at once and apply regular expressions?

This would at least work for your lowercase to uppercase example. Maybe you can apply many refactorings with this method and reduce the so needed hand made 'Sigasi refactorings' to a acceptable minimum.

Notepad++ can apply regexp replace rules on multiple files (apply to all open files).

PowerShell can be used to perform Linux like cat | sed operations:

Get-ChildItem . *.vhd -Recurse `
  | ForEach {Get-Content $_ -Encoding ASCII `
    | ForEach {$_ -replace "exit","----"} `
    | Out-File "$($_).new" -Encoding ASCII `
    }

This expression replaces every exit by ---- in all *.vhd files below the current directory. I renamed all output files to *.vhd.new

12
  • What's to prevent this from renaming something that is NOT a port name? If it will make that mistake, why is this a valid answer?
    – Ira Baxter
    Commented Apr 17, 2015 at 6:57
  • It's a rexexp and it's as powerful as you wish it to be. Your solution needs a whole language grammar for a simple replace.
    – Paebbels
    Commented Apr 17, 2015 at 7:25
  • Regexes are not as powerful as you want them to be. You did not answer the question. You could answer it by writing a regex that didn't make the mistake. I don't think you can.
    – Ira Baxter
    Commented Apr 17, 2015 at 7:30
  • As you can read below, Kevin posted a regexp to do this job! Modern regexps are not restricted to regular grammar! More over your suggested solution also uses a grammar that is based on regexp to parse tokens!
    – Paebbels
    Commented Apr 17, 2015 at 18:41
  • I believe you need to know which symbols are defined in which scopes to solve this problem right. I believe you have to parse the VHDL text to determine scopes and names-in-scopes. To the extent that your "modern regular expression" can "fully parse" the VHDL and do the name resolution, you might be right. But, if your modern RE can fully parse the VHDL, then your answer is essentially "use a parser"; to extent it cannot, it cannot. Assuming your modern VHDL fully parses, I fail to see how it handles the scoping problem.
    – Ira Baxter
    Commented Apr 17, 2015 at 21:05
0

You might consider program transformation tools (PTS). The tools let you define a grammar/parser (and an unparser) that reads source text and builds ASTs; you can then define and apply source-to-source transformations to the code-as-ASTs. When done, you use the unparser to regenerate valid source text.

Source to source transforms let you write patterns to recognize code of interest, and replace that code with modified code, all operating implicitly on the AST.

1
  • Ok guys thanks so far. I'll give this a try and will have a look at all of the options. Regards
    – daeda
    Commented Jan 26, 2015 at 9:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.