Как найти синтаксическую ошибку

когда я оцениваю функцию в одной ячейке, Mathematica говорит

ToExpression::notstrbox: {At Line = 6, the input was:,$Failed,InString[6]} 
is not a string or a box. ToExpression can only interpret strings or boxes 
as Mathematica input. >>

и правый край ячейки становится красным.

Как найти местоположение ошибки?

3 ответов


на самом деле ядро всегда отправляет на интерфейс позицию первой синтаксической ошибки во входной строке (если эта входная строка содержит ошибку). Это можно продемонстрировать с помощью следующего кода MathLink:

In[32]:= link = LinkLaunch[First[$CommandLine] <> " -mathlink"];
LinkRead[link];
LinkWrite[link, EnterTextPacket["2+"]]
LinkRead[link]
LinkRead[link]
LinkRead[link]

Out[35]= MessagePacket[Syntax, "sntxi"]    
Out[36]= TextPacket["Syntax::sntxi: Incomplete expression; more input is needed.
 "]    
Out[37]= SyntaxPacket[5]

целое число в SyntaxPacket "указывает позицию, в которой была обнаружена синтаксическая ошибка во входной строке" в соответствии с документацией. Что смущает сначала, так это то, что эта позиция в случае входной строки"2+" очевидно за пределами конец входной линии. Но кажется, что на самом деле эта позиция засчитывается за InputForm входной линии, которая в данном случае: "2+\n\n".

мы можем проверить, как она работает с $SyntaxHandler определен следующим образом:

In[41]:= link = LinkLaunch[First[$CommandLine] <> " -mathlink"];
LinkRead[link]
LinkWrite[link, 
 EnterTextPacket[
  "$SyntaxHandler=
      Function[{str,pos},
               Print["Input string: ",ToString[str,InputForm]];
               Print["Position of syntax error: ",pos];
               $Failed
      ];
  "]]
LinkRead[link]
LinkWrite[link, EnterTextPacket["2+"]]
While[Head[packet = LinkRead[link]] =!= InputNamePacket, 
 Print[packet]]; Print[packet]

Out[42]= InputNamePacket["In[1]:= "]    
Out[44]= InputNamePacket["In[2]:= "]    
During evaluation of In[41]:= MessagePacket[Syntax,sntxi]    
During evaluation of In[41]:= TextPacket[Syntax::sntxi: Incomplete expression; more input is needed.
]    
During evaluation of In[41]:= TextPacket[Input string: "2+\n\n"
]    
During evaluation of In[41]:= TextPacket[Position of syntax error: 6
]    
During evaluation of In[41]:= SyntaxPacket[5]    
During evaluation of In[41]:= InputNamePacket[In[2]:= ]

можно увидеть несоответствие между позициями той же синтаксической ошибки, сообщенной SyntaxPacket и $SyntaxHandler. Но кажется возможным понять, как они считают позицию: оба используют InputForm входной линии и положение до входная строка имеет номер 0 для $SyntaxHandler и номер 1 в случае SyntaxPacket. Таким образом, мы можем определить $SyntaxHandler для получения точного визуального представления положения синтаксической ошибки внутри входной строки (вход Cell должен иметь стиль "RawInputForm") следующим образом:

$SyntaxHandler = 
  Function[{str, pos}, 
   Print["Input string: ", ToString[str, InputForm], "\n", 
    "Position of syntax error: ", pos, "\n", 
    StringInsert[ToString[str, InputForm], 
     ToString[Style["\[DownArrowBar]", Red, Background -> Yellow], 
      StandardForm], pos + 2]]; $Failed];

я еще раз подчеркну, что входная ячейка должна иметь стиль "RawInputForm"! Такая ячейка может быть создана путем создания обычной пустой входной ячейки, а затем преобразования в "RawInputForm" ячейки соответствующей командой .

давайте посмотрим, как это работает:

screenshot

причина, по которой мы должны использовать ячейку "RawInputForm", вероятно, это $SyntaxHandler применяется ony, когда вход отправляется ядру в виде String, а не в форме Boxes как это происходит с default StandardForm входные ячейки.


ты называешь ToExpression себя на струне? Функция SyntaxLength даст вам смещение символов первой синтаксической ошибки при применении к строке, например:

In[26]:= SyntaxLength["2+"]
Out[26]= 4

In[27]:= SyntaxLength["x[1]+x[2]]"]
Out[27]= 9

обратите внимание, что, как указано в документации, когда SyntaxLength возвращает позицию за пределами конца входной строки, Что означает, что выражение синтаксически корректно, но неполно. В противном случае, SyntaxLength эффективно возвращает позицию первого синтаксиса ошибка.

если вы явно не вызываете ToExpression на что-то, это, вероятно, поможет увидеть рассматриваемую ячейку.


синтаксические ошибки, такие как несбалансированные функциональные скобки, обычно обозначаются с помощью раскраски символов, непревзойденная скобка становится розовой или около того. В этом случае произошла ошибка типа ввода. По-видимому, вы вызвали (или функцию, которую вы использовали) ToExpression, используя результат другой функции, которая не удалась. Первым шагом было бы найти это выражение и выяснить, какая функция, обеспечивающая его входные данные, возвращает $Failed.

Mathematica имеет отладчик голых костей, который вы можете найти в меню оценки. Лучший отладчик можно найти в Matimatica Workbench, который является бесплатным, если у вас есть лицензия Premier Service.

Если ваш код не слишком велик, я бы предложил опубликовать его как часть вашего вопроса. Но мы не сайт для проверки кода.