2011-11-27 6 views
11

セル式から抽出した任意のボックス指定を入力式に変換するにはどうすればよいですか?入力セルボックス式の解釈に関する問題

これは私の答えがSave Mathematica code in FullForm syntaxになったときに問題となりました。この文脈では、Importを使用して読み取られたノートブック式からボックス仕様を抽出するためにパターンマッチングが使用されていました。

ToExpressionまたはMakeExpressionはボックス解釈の仕事をすると思っていましたが、状況によってはそうではありません。

は表現が含まれている入力セルを考えてみます、このような細胞のための細胞発現は、このようになります

StringForm["a = ``", 1] 

Cell[BoxData[ 
RowBox[{"StringForm", "[", 
    RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]], "Input"] 

私は、このセルからBoxData部分式を取り、ToExpressionを使用することができます元のセルを評価したのと同じ結果が得られます。

ToExpression @ 
    BoxData[ 
    RowBox[{"StringForm", "[", 
     RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]] 
はイタリック体である:あなたは違いを確認するために密接に見てする必要があります

StringForm["a = ``", 1]

しかし、今は、次の入力式を考えます。対応するセルの式は次のとおりです。

Cell[BoxData[ 
RowBox[{"StringForm", "[", 
    RowBox[{"\"\<\!\(\* 
StyleBox[\"a\", 
FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]], "Input"] 

このセルを正常に評価すると、予想通りの結果が得られます。私は前のようなBoxData部分式にToExpressionを適用しようとした場合でも:

ToExpression @ 
    BoxData[ 
    RowBox[{"StringForm", "[", 
    RowBox[{"\"\<\!\(\* 
    StyleBox[\"a\", 
    FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]] 

エラーが発生します。

StringForm::string : String expected at position 1 in StringForm[]\) = '', 
FontSlant->"\~\(\*\nStyleBox["a Italic, 1]. 

すべてではない場合は、エラーの同じ種類は、インライン文字列]ボックスの脱出のため、多くのために発生しますシーケンス。明示的にフォームをToExpressionMakeExpressionに指定しようとしましたが、同じエラーが発生します。これは私の質問に私をもたらします...

Mathematicaが入力セル式からボックスを解釈する方法をエミュレートするにはどうすればよいですか?

答えて

5

これはバグだと思います。ここで私がテストした例をいくつに取り組んで回避策です:たとえば

Clear[toExpression]; 
toExpression[bd_BoxData] := 
    ToExpression[bd /. 
     s_String :> 
     StringReplace[ 
      StringReplace[s, "\n" :> ""], 
      ShortestMatch[(start : "\(\*") ~~ body__ ~~ (end : "\)")] :> 
        StringJoin[start, StringReplace[body, "\"" :> "\\\""], end] 
     ] 
    ]; 

が、私たちはあなたのケースで始まる:我々は今、細胞を調べると

In[747]:= 
BoxData["\"\<\!\(\* 
    StyleBox[\"a\", 
     FontSlant->\"Italic\"]\) = ``\>\""]//toExpression 

Out[747]= a = `` 

、それは次のようになります。

BoxData["\<\"\\!\\(\\*StyleBox[\\\"a\\\",FontSlant->\\\"Italic\\\"]\\)\ = ``\"\>"] 

代わりの

BoxData["\"\<\!\(\*StyleBox[\"a\",FontSlant->\"Italic\"]\) = ``\>\""] 

(改行を削除した最初のものです)。そして、私はこれが最初からあったはずだったと主張します。 Now:

In[746]:= [email protected] 
    BoxData["\<\"\\!\\(\\*StyleBox[\\\"a\\\",FontSlant->\\\"Italic\\\"]\\) = ``\"\>"] 

Out[746]= a = `` 

これはすでにうまくいきます。

これはどれほど普遍的かは分かりませんが、試した例ではうまくいくようです。主な問題は、aとのような文字列化の場合、\"a\"\"Italic\"ではなく、\\\"a\\\"\\\"Italic\\\"であり、エスケープ自体のエスケープが欠落しているはずです。

+0

@WReach私の初期の解決策は、まったく正しいとは言えませんでした。ちょうど私が発見したように、より複雑な表現には失敗していました。私は少し修正しました - 今は正しく動作するようです。 –

+0

あなたの更新版が、私が衝突したすべてのケースを処理します。私はもうすぐ別のアイデアが出てくるのを待って、もう少し長く "受け入れ"を延期するつもりです。私はここにバグがあることに同意する傾向がありますが、私は何か基本的なものが欠けているという感覚を揺さぶることはできません。あるいは、パーサーが利用できない隠された機能を使用していないことは無駄です。 – WReach

+0

@WReach私はこれが以下の単純な例で起こるのと同じタイプの情報損失だと思います:ToExpression [ToString ["a"]] // Head'( 'Symbol'を返します)。 'ToExpression'は、文字列に対して「文字列化」のレベルを下げます(それをより良くする方法はわかりません)。だから、 'ToExpression'の後ろに文字列を入れるには、ここで' '\" a \ "" 'を使っていたはずです。現在の状況は本質的に同じですが、レベル1についてはレベル2の文字列化が行われていますが、バグは「レベル1」のみが使用されているようです。 –

2

正直、私はあなたが何をしようとしているのかは分かりませんが、処理のためにFrontEnd自体を使用する必要があると思われます。一般的な例を次に示します:

[email protected]`CellPrint[ 
    BoxData[RowBox[{"StringForm", "[", RowBox[{"\"\<\!\(\* 
     StyleBox[\"a\", 
     FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]] 
] 

しかし、私はあなたが実際にどのようなフォーマットを取得したいのか分かりません。

+1

元のリンクされた質問の文脈では、目的は 'Import'または' NotebookGet'を使って得られたそのセル表現から入力式を再構成することでした。私は非常に驚いて、 'ToExpression'がその仕事にふさわしくないことを発見しました。 – WReach

関連する問題