Too many right parentheses? Auto Format fails.

I have a program that compiles without errors (about 900+ lines, 30%comments) and yet will not "auto format". Auto Format comes up with the status line "Too many right parentheses".

So far I have tried using the matching parentheses feature in the IDE which has bailed me out a number of times previously. However this time I just can't find it using that IDE feature. Painstakingly I have manually formatted/indented hoping to spot it. I have also used Notepad++ to highlight all occurrences and also use the indent lines to check to see what matched with what, but again no luck. All this time the program compiles, but is getting messier and I want to tidy it up. Finally I loaded the program file into Eclipse hoping it would be able to help pinpoint the problem, and to my surprise it just auto formatted the file and had it looking marvellous (again!) with no hint of non matching parentheses. Reloaded into IDE 1.0 and it was fine as before.

I don't want to have to repeat the Eclipse process each time I tidy up, so I am keen to hear of any tips or techniques that might crack this one for me.

Rob

It would have helped to post or attach the problem code.

I have had problems like this in the past (not relating to Arduino) where formatting tools were sensitive to line endings i.e. Windows/Max/Linux line ending conventions. Since the formatter has to parse the source code it needs to deal with whitespace and so on itself and may have quirks that aren't consistent with the compiler. I haven't had any encoding related problems (yet?) but it's something that might conceivably cause different tools to parse your code differently depending how they deal with special characters, so check whether you're using a plain old ascii text file or some other encoding.

I ran into the same issue and it turned out to be a parenthesis inside a quoted string. Funny thing was that the auto-format didn't notice the left parenthesis in the same string, only the right parenthesis. It never fixed anything, just complained that there was one too many. When I took out the offending string everything was fine.

Delta_G, you are very close...

Here is the offending line :

          //if (tempVar == 0){ //reset the midi clock so as soon as non-zero events come we have not wasted time (Sympton: First notes go too quick)

Remove this line and all is sweet with "Auto Format".

I had Commented out about 5 lines beginning with this 'if' statement using // on each line, but I would have thought anything after a "//" would be quickly ignored by the formatting parser.

A couple of hints I can pass on though

  1. () are Parentheses
  2. {} are Curly Braces
  3. XS for Right or Left are reported

How to find the line(s)?

Well I finally cracked it by taking chunks of code that were logical starts and ends to subsections of the program, and copying that chunk on its own into another window of the Arduino IDE and testing it. This meant I could quickly try a format and eliminate all the declarations at the start, then test the setup(), followed by all the subroutines after the void() etc etc.
Somewhere in the void() loop was the problem. I then chopped out large chunks in a binary chop of sorts (logic of the program permitting). The fault was in about the last 32th of the void() loop, but it did not take long to get down to testing individual lines, as I finally had about 20 that contained the fault in the second IDE window and selecting, ctrl-x, ctrl-t to format and then ctrl-z to restore lines quickly identified the culprit line.

As Delta_G said, the formatting parser may hiccup on other combinations so the above search and destroy method could be quite handy.

Personally I don't understand why that line should be a rogue (the parentheses do match and it is behind //?), apart from suggesting a bug in the parser, and far be it from my point of view to criticise someone else's work. The compiler was not confused and correctly ignored the line. The lines also compiled OK when included. Looking for a "programming fault" in a comment line was indeed a challenge!!

Cheers, Rob

PS I even got down to using MS-Word ]:slight_smile: to count the 411 () and in equal numbers, and 92 {} again in equal numbers, but as the line above revealed the logic of what went wrong is beyond me.

Raised as a bug here:

http://code.google.com/p/arduino/issues/detail?id=974

Cheers Nick,

Thanks, a good few hours (days?) on that one :~,

Rob

it turned out to be a parenthesis inside a quoted string.

I've had something similar where I left out a terminating quote in a string
used as a passed argument ... eg Serial.print("hello, dummy); instead of
Serial.print("hello, dummy"); ... so the compiler ran down the road until it
found another quote to use as the terminator.

IOW, the compiler didn't catch an error, and thought that ); here was
just part of a string, but then the program crashed when running.
IOW, quotes have a higher precedence to the compiler than either
) or ;.

IOW, maybe the OP's problem is upstream of the "offending" line.

Read the bug report I submitted. I reproduced it with a single line. No quotes where harmed in the production of this bug.

However I don't doubt that you might get a similar effect with mismatched quotes.

Thanks for the interest in this folks. The point about something being upstream was also worth checking out, so I am wondering if this should be logged as well Nick if I include the preceding and following lines.

long tempVar = (varVar()*(tempoMidi+deltaTempo)/ticksPerBeat)/1000;
//if (tempVar == 0){ //reset the midi clock so as soon as non-zero events come we have not wasted time (Symptom: First notes go too quick)
// midiTime[trackCounter] = millis();
// beatTime = midiTime[trackCounter];
//}

What I have tested is that if I just remove the //if (tempVar.... line the whole program formats and compiles OK. So I think it is just that line, though why it is so sensitive could still be triggered by the preceding line. It may not like how I have used the parentheses to force the order of calculation (to help retain maximum accuracy in a non-floating point result).

Interesting is the fact that even if this small segment is copied into a new Sketch, the formatting parsing error can be replicated and if the line is removed, it goes away :smiley: If the preceding program statement is removed the problem continues.

Like finding a needle in haystack, when it was actually a supposed innocuous hayseed that was really the problem, a comment! Now back to work.. more code.. more code...

Cheers, Rob

robwlakes:
It may not like how I have used the parentheses to force the order of calculation (to help retain maximum accuracy in a non-floating point result).

I'd be disappointed if it objected to that - it's entirely reasonable and normal to do that imo.

All these issues stem, apparently, from having comments following code that is commented out. That's why I hate trailing comments. If the comment is really useful, put it on its own line(s) before the block of code.

Then, if you need to comment out the code, no comments get mangled, and the auto formatter works.

Read the bug report I submitted. I reproduced it with a single line. No quotes where harmed in the production of this bug.

Actually, I didn't understand the bug report, because the long-comment line
wraps around on the screen, and doesn't have // on the 2nd line, so I couldn't
tell is that was just a side-effect of the display editor or not.

All these issues stem, apparently, from having comments following code that is commented out. That's why I hate trailing comments. If the comment is really useful, put it on its own line(s) before the block of code.

I wonder if it works better to use /.../ style comments at the end of a line
of code. ???

I wonder if it works better to use // style comments at the end of a line
of code. ???

// I don’t think so. Any style of comment is meant to explain what some line(s) of code
/* are supposed to accomplish. Comments at the end of a statement, like: */

if(i < 4) // if i is less than four
{
}

// are useless. Any one with half a brain can see what the code does.

In my opinion, comments at the end of code should not be used. Any time I use them, it is only during development, to remind myself what should happen in the block. I move them inside the block if they
are really useful, when I develop the code for the block.

Whether the comment is of the /* style */ or the // style is really irrelevant.

// are useless. Any one with half a brain can see what the code does.

No matter what, comments need to be better than just repeating the exact same
thing. Some people use extra_long_descriptive_labels_so_functionality_is_obvious,
but I prefer very short labels with descriptive comments, and terse source listings.
Eg, from one of my sketches:

// VDD = cpu_buss_voltage, set to 33 or 50.
const int VDD = 33;    // cpu buss voltage=3.3V.

#define noKEY   -1     // indicates no user input.

#define fDISP    TRUE   // indicates display something.
#define fNDISP  FALSE

/***** ServoTank I/O Pin Assignments *****/
// analog
#define anBATT     0  // battery voltage.
#define anEYEL     1  // left-side LDR.
#define anEYER     2  // right-side LDR.
#define anRNGR     3  // GP2D12 IR ranger.

// digital
#define XBeeRX     2  // XBee receive.
#define XBeeTX     3  // XBee transmit.
#define PZpin      5  // piezo beeper.
#define PINGRpin   6  // EZ4.
#define PINGLpin   7  // EZ1.
#define IRPDRpin   8  // right-side IRPD.
#define IRPDLpin   9  // left-side IRPD.
#define SVTpin    10  // tilt servo.
#define SVPpin    11  // pan servo.
#define SVLpin    12  // left-drive servo.
#define SVRpin    13  // right-drive servo.

#define TRUE      true
#define FALSE     false

// Multi-Level Signalling Flags.
#define isBAD    -99  // indicates sensor non-functional, etc;
                      // used w/sensors that cannot have values < 0.
#define isOFF      0
#define isON       1
#define isOK       2
#define isNBUSY    3  // not-busy.
#define isBUSY     4
#define isLEFT     5
#define isRIGHT    6

// actions for panning Pan-Servo.
#define pnSTOP     0    // stop panning.
#define pnHOME     1    // move to home position = front.
#define pnWIDE     2    // execute automatic wide panning scan.
#define pnNARR     3    // execute automatic narrow panning scan.

// control-list operations.
#define fREPLAC    1    // replace all items in control-list. 
#define fAPPEND    2    // append item to end of control-list. 

// FSM control.
#define fNULL     -1    // null operation.
#define fABS	   1    // treat velocity setting as absolute.
#define fINCR      2    //   "       "       "    "  incremental.
#define fMAX       3    // set velocity to specified value, if not less than already.

but I prefer very short labels with descriptive comments, and terse source listings.
Eg, from one of my sketches:

I don't have any problem with that code. On the other hand,

// battery voltage.
#define anBATT     0

conveys the same information in the same space, except for the extra line feed.

It's a matter of style, and understanding the impact of commenting out a line of code.

PaulS:
All these issues stem, apparently, from having comments following code that is commented out. That's why I hate trailing comments.

Not so, however. This code will not auto-format:

void setup ()
{
}

//if (tempVar == 0){ reset the midi clock so as soon as non-zero events come we have not wasted time (Sympton: First notes go too quick)

void loop () {
}

On the face of it, a line which is purely a comment, and without imbedded comments, should format correctly.

That is even more interesting Nick,
Though I do confess to using the // comment system first for the documenting comment, and later reusing it again as a quick debug strategy, both of which are acceptable I believe and likely to occur in that combination frequently. The school boy mantra of "anything can be placed in a comment" is still ok with me.

I have taken Nick's example and loaded into the IDE and it replicates the error, but if I delete out the first pair of parentheses, the format error goes.

Even more interesting-
If the parentheses are deleted in the second pair the error also goes.
Back to the original line and remove the first pair of parentheses separately, reformat each time and I think you will find the end of the line goes crazy when reformatted.

//if (tempVar == 0){ reset the midi clock so as soon as non-zero events come we have not wasted time (Symptom: First notes go too quick)
.... reformat - too many right parentheses, now remove first right parentheses -
//if (tempVar == 0{ reset the midi clock so as soon as non-zero events come we have not wasted time (Symptom: First notes go too quick)
.... reformat - too many right parentheses, now remove first left parentheses -
//if tempVar == 0{ reset the midi clock so as soon as non-zero events come we have not wasted time (Symptom: First notes go too quick
.... reformat - works OK but notice that the second right parentheses has mysteriously disappeared?

It appears the double pair of parentheses may be the trigger?

I made a hex dump of the line to see if there was some hidden character I had somehow introduced that was the problem but as far as I can see it is just standard ASCII as might be expected in text. If the line is typed in manually and not copied the same error persists.

"000000000  2F 2F 69 66 20 28 74 65-6D 70 56 61 72 20 3D 3D   |//if (tempVar ==|"
"000000010  20 30 29 7B 20 72 65 73-65 74 20 74 68 65 20 6D   | 0){ reset the m|"
"000000020  69 64 69 20 63 6C 6F 63-6B 20 73 6F 20 61 73 20   |idi clock so as |"
"000000030  73 6F 6F 6E 20 61 73 20-6E 6F 6E 2D 7A 65 72 6F   |soon as non-zero|"
"000000040  20 65 76 65 6E 74 73 20-63 6F 6D 65 20 77 65 20   | events come we |"
"000000050  68 61 76 65 20 6E 6F 74-20 77 61 73 74 65 64 20   |have not wasted |"
"000000060  74 69 6D 65 20 28 53 79-6D 70 74 6F 6E 3A 20 46   |time (Sympton: F|"
"000000070  69 72 73 74 20 6E 6F 74-65 73 20 67 6F 20 74 6F   |irst notes go to|"
"000000080  6F 20 71 75 69 63 6B 29-0D 0A                     |o quick)..      |"

And as to seeing what the code does- yes that is obvious, but is it easy to quickly recall what the purpose of the code is? Small problems = small comments, use what works, agreed.

I don't know if this helps, or is relevant, but I do know that it is hard to parse C syntax correctly with a regular expression. You can do it with a PEG (Parsing Expression Grammar) but with a regular expression the case of nested brackets/quotes is not easy to handle.

Information about PEGs:

http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html

http://bford.info/packrat/