我需要将用户类型的表达式编译为可以调用的.NET程序集。表达式语言(从应用程序的版本1继承)非常有限,并且几乎是有效的C#,但它确实具有一些不寻常的属性。
我想在版本2中切换到完整的C#,但是在使用Roslyn将特质转换为可编译的SyntaxTree时遇到问题。此刻,我正试图弄清楚如何获得力量和阶乘进行编译,即
double n = 1.5² / 0.9³ + 6!;
必须转换为类似的内容:
double n = Pow(1.5, 2) / Pow(0.9, 3) + Factorial(6);
但是,当我解析原始表达式时,所有这些立即在²
字符处分解:
public static void TestLanguageAdditions()
{
const string code = "double n = 1.5² / 0.9³ + 6!;";
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var syntaxRoot = syntaxTree.GetRoot();
var sb = new StringBuilder();
sb.AppendLine(code);
sb.AppendLine();
foreach (var node in syntaxRoot.DescendantNodes())
{
var span = node.FullSpan;
var spanLine =
new string(' ', span.Start) +
new string('●', span.Length);
spanLine = spanLine.PadRight(30);
spanLine += ((CSharpSyntaxNode)node).Kind();
sb.AppendLine(spanLine);
}
string report = sb.ToString();
Console.Write(report);
}
收益:
double n = 1.5² / 0.9³ + 6!;
●●●●●●●●●●●●●●●●●●●●●●●●●●●● FieldDeclaration
●●●●●●●●●●●●●● VariableDeclaration
●●●●●●● PredefinedType
●●●●●●● VariableDeclarator
●●●●● EqualsValueClause
●●● NumericLiteralExpression
我想知道是否有任何办法哄Roslyn照原样解析字符串的其余部分,否则,准备字符串的好策略是什么?显然,我可以用一些可解析的占位符替换²
和³
字符,但是当这些字符出现在字符串或字符常量中时,则不能。
-----------------------------------编辑----------- ------------------------
将非法字符转换为块注释可以进行解析,尽管奇怪的是,它们在许多节点之后都显示为琐事:
double n = 1.50/*²*/ / (0.90)/*³*/ + 6/*!*/;
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● CompilationUnit
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●● FieldDeclaration
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●· VariableDeclaration
······································●●●●●· ˃ trivia: /*!*/
●●●●●●●····································· PredefinedType
·······●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●· VariableDeclarator
······································●●●●●· ˃ trivia: /*!*/
·········●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●· EqualsValueClause
······································●●●●●· ˃ trivia: /*!*/
···········●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●· AddExpression
······································●●●●●· ˃ trivia: /*!*/
···········●●●●●●●●●●●●●●●●●●●●●●●●········· DivideExpression
·····························●●●●●·········· ˃ trivia: /*³*/
···········●●●●●●●●●●······················· NumericLiteralExpression
···············●●●●●························ ˃ trivia: /*²*/
·······················●●●●●●●●●●●●········· ParenthesizedExpression
·····························●●●●●·········· ˃ trivia: /*³*/
························●●●●················ NumericLiteralExpression
·····································●●●●●●· NumericLiteralExpression
······································●●●●●· ˃ trivia: /*!*/