15

In a package I am developing, I accidentally left this line

Protect[

uncompleted prior to running the package. Mathematica produced this error message

Syntax::sntup: Unexpected end of file (probably unclosed parenthesis)
              (line 102 of "DataListPlot`").

which includes the line number of the error. Since the code was short and it was the only thing in that cell, it was straightforward to find. But, in general, how would one find a specific line in a package? Also, is it possible in the standard package interface to add line numbers, like in WorkBench?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
rcollyer
  • 33,976
  • 7
  • 92
  • 191
  • 1
    Open the .m file in an editor and go to that line? Although in this case, the line mentioned would not have helped much because it was the end of the file (not hard to find anyway), while the error was much earlier (but a good editor with paren matching would probably have helped with that problem, too). – celtschk Apr 02 '12 at 17:49
  • @celtschk that is definitely an option, but since mma gave me the error message wherein it discusses a line number, I was hoping for a solution within mma. – rcollyer Apr 02 '12 at 17:58
  • Just a wild thought... If we can have some code indenting and formatting rules for the package files, then we can talk about "line 142 under Kernel style", "line 120 under GNU style", etc., and we can have a LineNumberConvert function to convert between different styles... Just a wild thought... :) – Silvia Aug 04 '14 at 06:39

1 Answers1

13

There is a certain impedance mismatch between lines of code and Mathematica expressions, because Mathematica code is written more or less directly in the parse trees, and the syntax (which encourages nested expressions) was not particularly designed to make lines a really good concept here. That said, this would be a problem in any language, to various extents, because, while you know what you meant in the code and what the error is, the parser may interpret things differently (this is the difference between syntax and semantics). For example, your particular error which you mentioned in the question will be interpreted as a bracket not closed at the end of file, not where you think it really happens (because the parser thinks that the rest of the code is within an opening bracket of Protect).

In any case, the following function will (hopefully) at least tell you what parser thinks, in terms of line numbers:

ClearAll[getErrorLine];
getErrorLine[filename_String] :=
 Module[{code, lengths},
    code = Import[filename, "Text"];
    lengths = StringLength /@ StringSplit[code, "\n"] + 1;
    With[{sl = SyntaxLength[code]},
      LengthWhile[Accumulate[lengths], # < sl &]
    ]
 ]

For a test package like this (all new lines intact):

BeginPackage["SyntaxTest`"]

f::usage;

Begin["`Private`"]

g[x_]:= x^2;

f[x_]:=Sin[g[x]

End[]

EndPackage[]

it gives

getErrorLine["C:\\Temp\\SyntaxTest.m"]

13

which is, at the end of the package. And this is correct, since you can not assign a well-defined semantics to a syntactically broken code, so you can only ask what parser thinks.

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • In an attempt to impose some organization on my code, my packages are broken up into cells, and that particular statement is in a separate cell. So, as far as I am aware, the parser should not cross cell boundaries when interpreting the code. This, of course, improves the likelihood of being able to find the bad code. – rcollyer Apr 02 '12 at 18:08
  • @rcollyer When you look at your package in a usual text editor, how do these cells manifest themselves? What kind of special symbols or separators are there to tell the parser where one cell ends and another one starts? – Leonid Shifrin Apr 02 '12 at 18:13
  • @rcollyer: AFAIK the .m file does not contain the cell structure (if you edited it directly from Mathematica, it contains comments from which the cell structure can be inferred, but of course the parser ignores comments). – celtschk Apr 02 '12 at 18:14
  • @celtschk Ha! It uses double spaces, not comments. Prior, I was just using single spaces within a "cell," but upon adding a double space and reloading, it split the cell. And, it appears Leonid is correct, it runs to the end of the file before stopping. – rcollyer Apr 02 '12 at 18:31
  • @LeonidShifrin considering that mma is only giving me the end of file, then your answer is probably as far as we can get with this. – rcollyer Apr 02 '12 at 18:36
  • @rcollyer There wouldn't be any other (than go to the end) way for the parser to behave, because these spaces (cell separators) are not a part of the syntax, and neither are these cells themselves. People often may wish to put really large chunks of code (up to an entire package body) inside some With or Module - possibilities which would be ruled out otherwise. Generally, the only things that the parser must respect are those related to parsed expressions being syntactically correct (with a few subtleties, related to parser working line-by-line). – Leonid Shifrin Apr 02 '12 at 18:37
  • @rcollyer I also think so. Any "partial" problem formulation for the parsing purposes can not (I suspect) be made precise and unambiguous. Thanks for the accept b.t.w., and sorry if my answer disappointed :-) – Leonid Shifrin Apr 02 '12 at 18:39
  • It is what it is. If I had pulled it up in a text editor, I might have seen it myself. – rcollyer Apr 02 '12 at 18:43
  • What about the second part: Is it possible to go to that line in mma? I'm a tired of opening Notepad++ just to navigate to a specific line... – Ajasja Apr 03 '12 at 17:41
  • 1
    @Ajasja I don't think it's possible within the notebook interface (or at least not without much extra effort), but I may be wrong. – Leonid Shifrin Apr 03 '12 at 17:51