harangzsolt33 has asked for the wisdom of the Perl Monks concerning the following question:

Have you ever had a perl script that is like 20000 lines long and you make some changes to it and then try to run it, and Perl says there's a syntax error on line 22193 where it's missing a closing curly brace. And you scroll down to that line, and it's the end of the file.

GREAT! I don't know where I made the mistake, but now I am expected to inspect the entire code to find that one missing curly brace. I already forgot where I made the changes. Is there a tool that can show me where I made this type mistake? How do you do this? Help!

  • Comment on How do I find the missing curly brace??

Replies are listed 'Best First'.
Re: How do I find the missing curly brace??
by GrandFather (Saint) on Dec 30, 2024 at 22:14 UTC

    Looking at some of the code you have published on PerlMonks I notice that your indentation and coding style can be a bit mixed. Using consistent indentation and coding style makes it harder to mismatch paired constructs and makes it easier to find errors when you do manage to get it wrong.

    Decent editors allow you to jump between matching parentheses, brackets and so on. With consistent indentation you can work through blocks in your code jumping between brackets until you find an indentation mismatch.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      ^ That. All of it.

      A decent editor/IDE will help track these types of issues down quickly, but a consistent coding style and layout will help prevent the developer from causing these issues in the first place, while providing simpler at-a-glance discrepancy finds even if a decent editor isn't available if a mistake is made.

Re: How do I find the missing curly brace??
by 1nickt (Canon) on Dec 30, 2024 at 16:39 UTC

    Use version control. Then it won't matter if you forget where you made the changes.


    The way forward always starts with a minimal test.

      Not only does version control let you go back to a previous version, you can diff your current version against an earlier version and see exactly where you made changes. For an error of the OP's sort you can usually then look at a few lines around the change areas and quickly spot the issue.

      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
      Use version control.

      Whether a beginner developer or someone who's inherited someone else's code, learning how to use a VCS should be step 0.

Re: How do I find the missing curly brace??
by karlgoethebier (Abbot) on Dec 30, 2024 at 17:45 UTC
Re: How do I find the missing curly brace??
by LanX (Saint) on Dec 30, 2024 at 20:57 UTC
    maybe the fastest possibility to find such a bug without knowing the last healthy state:

    • use perltidy to indent the whole file, should generate a separate .tdy file by default
    • grep all occurrences of "{" and "}" into a separate file
    • go to the end of file and scroll back till the indentation looks normal

    I tried this with a 30k lines module and the output had 5k lines.

    you'll get something like this which is easier to be checked visually:

    One extra hint: since nesting subs is rare in Perl I'd also grep for sub keywords which are (unusually) intended.

    That's only 600 lines in this case.

    Apply perltidy -csci=0 -csc for "closing side comments" everywhere to identify the closing } of sub, if, etc.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      perltidy is a good suggestion. Similarly, vim or some other editor that does highlighting or highlights the start/end of the current BLOCK, might be useful. I wonder if perlcritic would similarly be useful? And maybe as a final stab, perl -c.
        perl -c will just reproduce the same error he already reported.

        But probably he can do a binary search by only compiling the first half of the source.

        If it works add a quarter, otherwise subtract one.

        And so on, till he identified the problem...

        I think he will need to do the splitting manually tho, and can't rely on an automatic bisect.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

      These are some really good ideas. Thank you! I like especially this one:

      "since nesting subs is rare in Perl I'd also grep for sub keywords which are (unusually) intended."

Re: How do I find the missing curly brace??
by Paladin (Vicar) on Dec 30, 2024 at 18:15 UTC
    Everyone has given lots of great advice so far, but to show you why this is a non-trival problem conciser the following code with a missing }.
    if ($foo) { print "A\n"; print "B\n"; print "C\n";
    Where is the missing } ? There's many places it could go and be a valid program. Only you, the programmer, knows which is the correct location.
Re: How do I find the missing curly brace??
by NERDVANA (Priest) on Dec 31, 2024 at 01:56 UTC

    In a project I maintain with 170K lines of perl (excluding generated code), the longest file is 4500 lines and the second-longest is 2884 lines.

    I know this probably seems like an unhelpful suggestion for your current situation, but you should consider being nice to yourself and divide your project into smaller modules.

      many things that look complicated at first (using strict, subroutines, modules, options, POD, version control, etc.), can and in fact do alleviate things (and perhaps life in general)
Re: How do I find the missing curly brace??
by stevieb (Canon) on Dec 31, 2024 at 09:39 UTC
    Have you ever had a perl script that is like 20000 lines long

    Yes, inherited.

    Learn VCS. Learn to commit small pieces with detailed but concise messages. Then break that up into multiple functional subroutines. Each sub should do only one thing (if possible), and its name should reflect what it does. If at all possible, try to keep the length of each sub so you can see the entire thing on one screen.

    Capture data from the script now (specifically print out information from each small piece you're going to change), write tests for each small piece you're going to migrate to a subroutine or other library, ensure the new code does what the old code does, then move on to the next section. Now you've got regression tests.

Re: How do I find the missing curly brace??
by LanX (Saint) on Dec 30, 2024 at 18:03 UTC
    That's not trivial without knowing the previous version.

    apart of using version control (like already mentioned)

    For instant feedback

    • run perl -c continuously in the background ( e.g. flycheck in emacs, default in Komodo)
    • use automatic indentation while typing

    For delayed analysis

    • jump thru the last edits your editor recorded ( goto-last-change in emacs )
    • indent the whole file, use perltidy if your editor doesn't support this ( indent-region in emacs) and do a visual check
    • diff with the backup file your editor generated
    • use tybalt89's suggestion to jump to the opening curly parsed by the editor for every closing one you find
    update

    perltidy has some additional features for code analysis, have a look.

    IIRC there is also one to add extra info in a comment after each closing block.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

Re: How do I find the missing curly brace??
by tybalt89 (Monsignor) on Dec 30, 2024 at 16:59 UTC

    In vim, add a closing brace to the end of the file, then put the cursor on that brace and in normal mode, press '%'. It should take you to the matching opening brace.

      this will bring him to the opening curley in the first level, not necessarily the one he's looking for.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

      Thank you!
Re: How do I find the missing curly brace??
by tybalt89 (Monsignor) on Dec 30, 2024 at 17:52 UTC

    Use perl to find perl errors.

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11163431 use warnings; my @what_lines; @ARGV = '3raindeermaze.pl'; # FIXME while( <> ) { for ( split // ) { /\{/ ? push @what_lines, $. : /\}/ ? pop @what_lines : 0; } } print "line numbers with unmatched { => @what_lines\n";

    Comment out the ARGV line to use your file as the argument to the program.
    ( I just did that for testing. )

      consider this convoluted example (Perl would catch this anyway)
      sub bla { print "yadda"; my %hash = { foo => 1, ); }

      the problem is in line 3, but your code will report line 1.

      and if you add a # } after a comment in line 2 it won't report anything.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

Re: How do I find the missing curly brace??
by naChoZ (Curate) on Feb 06, 2025 at 14:23 UTC

    Lots of great answers and advice already that are worth considering.

    Another simple technique that I use is from a vim feature using the [%] key. If you're on an opening (or closing) brace, bracket, or paren, hitting [%] will take you to the corresponding brace/bracket/paren. So, position yourself on an opening brace, take note of your indentation level, and hit [%]. If the brace it takes you to is not at that same indentation level, you've probably found your culprit.

    It's not perfect, but it's really fast, even in a long script, and it's right often enough to make it worth trying that first.

    --
    Andy

      That would be great where consistent indentation and code style are used. That is not a feature of the OP's code. :-(

      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond