2012-06-08 92 views
1

我只是想簡單的解析表達式一樣 -解析表達式並檢索分析樹的最簡單方法是什麼?

IIF(FVAL(PFC) = TRUE, (IIF((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500, (FVAL(BAS) + FVAL(DA)) * 12%, 780)), 0)` 

解析這個我應該能夠知道什麼功能包含哪些參數之後。

|-FVAL 
     |-PFC 
|-ORGVAL 
     |-BAS 
     |-"2012/12/31" 

我卡與.net Framework 2.0的,所以沒有LINQ的或我lambda表達式的好東西。此外,我想將代碼包含在自定義庫中,而不僅僅是引用它。任何人都可以指向我一些好的圖書館或代碼。

我只需要解析並不評估表達式並找到正在使用的令牌。找到後令牌我需要解析之前改變表達字符串,如如果函數ORGVAL被使用,則通過該參數具有必須由一個下劃線前綴。像ORGVAL(BAS)將轉換爲ORGVAL(_BAS)。有些功能可以拖參數,如ORGVAL(BAS, "2012/12/31"),這將轉化爲ORGVAL(_BAS, "2012/12/31")

注意:如果在做它,請讓我知道的其他方式。我會很樂意避開一個PARSER和LEXER。

+0

ANTLR。或者另一個語法分析器.. – nothrow

+0

@Yossarian ANTLR對我來說太難了。我對此一無所知。也許更簡單一些。 –

+0

忽略一個常見的解決方案使得這成爲購物問題的標誌。在所有SE網站上關閉主題。 –

回答

1

如果您不介意使用其中一種.NET語言作爲代碼,那麼您可以使用CodeDom進行編譯,然後將代碼作爲內存中的程序集執行。舉例來說,這將是最接近的例子表達你表明:

private abstract class Logic 
{ 
    protected double FVAL(object arg) 
    { 
     // put code here 
     return 0; 
    } 

    protected double ORGVAL(object arg) 
    { 
     // put code here 
     return 0; 
    } 

    protected double ORGVAL(object arg, string date) 
    { 
     // put code here 
     return 0; 
    } 

    public abstract double GetValue(object PFC, object BAS, object DA); 
} 

private class DynamicLogic : Logic 
{ 
    public override double GetValue(object PFC, object BAS, object DA) 
    { 
     return (FVAL(PFC) = true ? ((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0); 
    } 
} 


private Logic GenerateLogic(string code) 
{ 
    using (CSharpCodeProvider provider = new CSharpCodeProvider()) 
    { 
     StringBuilder classCode = new StringBuilder(); 
     classCode.AppendLine("private class DynamicLogic : Logic"); 
     classCode.AppendLine(" {"); 
     classCode.AppendLine("  public override int GetValue(object PFC, object BAS, object DA)"); 
     classCode.AppendLine("  {"); 
     classCode.AppendLine("   return (" + code + ");"); 
     classCode.AppendLine("  }"); 
     classCode.AppendLine(" }"); 
     CompilerParameters p = new CompilerParameters(); 
     p.GenerateInMemory = true; 
     p.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); 
     CompilerResults results = provider.CompileAssemblyFromSource(p, code); 
     return (Logic)Activator.CreateInstance(type); 
     if (results.Errors.HasErrors) 
     { 
      throw new Exception("Failed to compile DynamicLogic class"); 
     } 
     return (Logic)results.CompiledAssembly.CreateInstance("DynamicLogic"); 
    } 
} 

private double evaluate(object PFC, object BAS, object DA) 
{ 
    Logic logic = GenerateLogic("FVAL(PFC) = true ? ((ORGVAL(BAS, \"2012/12/31\") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0"); 
    return logic.GetValue(PFC, BAS, DA); 
} 

編輯:我知道你說你需要真正得到表達三個本身,而不僅僅是評價它,但我的工作代碼,所以我想我會繼續前進,並將其發佈給未來的路人。

+0

我們嘗試過這種方法,這非常慢。我們轉而使用[Flee](http://flee.codeplex.com/)。這要快得多。但對於一些仍在進行中的不良技術設計,我需要根據某些邏輯改變表達式。無論如何,我想要做的就是用'_BAS'替換BAS。 –

1

你想做的事聽起來很像解析,所以我不認爲你會找到一個不涉及解析的解決方案的運氣。如果你想說的是你不想自己編寫解析器,那麼有幾個數學表達式解析庫可用。

我是Jep.Net(http://www.singularsys.com/jep.net)的作者之一,它是一個表達式解析組件,可能適合您的需求。它是有據可查的,高度可定製的,並且肯定會讓您跳過實施自己的自定義分析器的繁瑣且容易出錯的過程。如果它不適合你,谷歌搜索「.net表達式解析庫」將讓你其他庫。

祝你好運!

相關問題