如何查找语法错误

时间:2011-06-22 00:46:23

标签: wolfram-mathematica

当我评估一个单元格中的函数时,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 个答案:

答案 0 :(得分:9)

实际上,内核总是将输入字符串中的第一个语法错误的位置发送到FrontEnd(如果此输入字符串包含错误)。可以使用以下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之前的位置输入行的数字为$SyntaxHandler的数字0和数字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”样式!可以通过创建普通的空输入单元然后通过Cell -> Convert To菜单中的适当命令将其转换为“RawInputForm”单元来创建这样的单元。

让我们看看它是如何运作的:

screenshot

当输入以$SyntaxHandler的形式发送到内核时,我们必须使用“RawInputForm”单元格的原因可能是String,而不是Boxes的形式1}}与默认的StandardForm输入单元格一样。

答案 1 :(得分:6)

你是否在自己的字符串上调用ToExpression?函数SyntaxLength将在应用于字符串时为您提供第一个语法错误的字符偏移量,例如:

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

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

请注意,正如文档中所示,当SyntaxLength返回超出输入字符串末尾的位置时,这意味着表达式在语法上是正确的,但是不完整。否则,SyntaxLength会有效地返回第一个语法错误的位置。

如果您没有明确地在某些内容上调用ToExpression,则可能有助于查看相关单元格。

答案 2 :(得分:4)

语法错误(例如不平衡的功能括号)通常通过字符着色来表示,不匹配的括号变为粉红色等。在这种情况下,存在输入类型错误。显然,您使用失败的另一个函数的结果调用(或您使用的函数)ToExpression。第一步是找到这个ToExpression并找出提供其输入的函数返回$ Failed。

Mathematica有一个简单的调试器,你可以在评估菜单中找到它。如果您拥有Premier Service许可证,可以在Matimatica Workbench中找到更好的调试器。

如果您的代码不是太大,我建议您将其作为问题的一部分发布。但是,我们不是代码审查网站。