【问题标题】:Regex to find variables in code正则表达式在代码中查找变量
【发布时间】:2013-08-14 19:54:28
【问题描述】:

我正在创建一个程序,使用户能够创建某种脚本。我在运行时编译他的脚本然后执行。我正在做类似的事情:https://stackoverflow.com/a/4181855/637142

无论如何,为了让长话短说,基本上我必须替换所有以 $ 开头的变量。用于使脚本编译的东西。 如果用户有以下行:

var x = ($MyArray[ 4 ].Size) + 3;

什么正则表达式可以让我选择$MyArray[ 4 ].Size

如果用户在哪里写:

var x = $SomeVar;

在这种情况下,很容易找到 SomeVar 。我无法找到以 $ 开头的变量

编辑

我想我已经快要找到解决方案了。现在我将 $ 替换为 Foo. ,换句话说,我替换了该行:

var x = ($MyArray[ 4 ].Size) + 3;

dynamic Foo; // then
var x = (Foo.MyArray[ 4 ].Size) + 3;

现在它可以编译了,但我仍然需要找到 Foo.MyArray[ 4 ].Size

编辑 2

我不是想创建一个编译器,我只需要替换一些变量(以 $ 开头的变量)而已;)

【问题讨论】:

  • 为什么需要找到Foo.MyArray[ 4 ].Size 而不是Foo?他们都应该完成替换$
  • RegEx 不是适合这里工作的工具。正则表达式只能解析正则语言,C#(和大多数其他编程语言)是上下文无关语言,需要基于下推自动机的不同模型进行解析。如果您在谷歌上搜索这些术语,您可以了解其背后的理论。但基本上,我向你保证,没有足够的正则表达式。
  • 是的,我相信我很擅长正则表达式,几乎不可能创建它。
  • 你将如何处理包含"This is $NotAVariable" 的字符串?还是评论中的相同内容?我认为你低估了问题的复杂性。
  • @icemanind:我的意思是,正则表达式方法不仅仅可以重命名变量。它还会重命名字符串文字和 cmets 中的值。

标签: c# regex parsing


【解决方案1】:

听起来您正在尝试使用正则表达式将脚本语言转换为另一种语言。正确执行此操作所需的内容远远超出正则表达式所能管理的范围。

我强烈建议您使用现有的解析系统来为您管理脚本,因为他们会考虑许多此类外部因素并创建一种成熟的语言来工作。例如,Lua 是一种常见的选择。

或者,您可能想要编写一个适当的解析器来处理将原始源代码转换为一个树,然后可以遍历该树以生成结果代码。

【讨论】:

    【解决方案2】:

    我不确定我是否完全理解了这个问题。

    您正在尝试制作编译器?我的朋友,这并不容易。编译器一般会经历 5 个阶段:

    • 词法分析
    • 解析
    • 语义分析
    • 优化
    • 代码生成

    在我看来,您正在尝试完成词法分析阶段。如果是这样,您可以使用许多程序来完成此任务。其中一种工具称为 C# LEX。它是生成分析代码和生成标记的程序的绝佳工具。

    这是一个 LEX 脚本示例:

        %%
    
        ALPHABET = [a-zA-Z]*
    
        %%
    
        <YYINITIAL>{ALPHABET} { return ("STRING"); }
    

    C# LEX 获取这个 .lex 文件并对其进行解析。然后它会生成一个 C# 程序,该程序可以分析任何符合词法分析器指定语言的脚本。

    谢谢,

    【讨论】:

      【解决方案3】:

      花费大量时间后设法执行正则表达式。

      如果我有代码:

      if (0 == $Foo.Arr1[7 + Arr2_5[3-1] ].More[8].Yes-9) {
        // do something
      } 
      

      在这种情况下,我想匹配$Foo.Arr1[7 + Arr2_5[3-1] ].More[8].Yes

      以下正则表达式将匹配:

      (?xi)
      (?>
            (?<Q> "      )    # quote
          | (?<C> //     )    # comment
          | (?<N> [^"\$] )    # nothing
          | (?<D> \$     )    # dollar sign
      )
      (?(Q) .+? (\r|\n|$|") ) # if a quote is match continue selecting until you find next quote
      (?(C) .+? (\r|\n|$)   ) # if a comment // or /* is match continue selecting until end of line
      (?(N) (?=(?!))        )
      (?(D)                   # if dollar sign is matched then:
        (
      
          (?(B)(?<-B>)){15}  # make sure group has a count of 0
      
          (?<V> [a-z|_]     ) # variable must start with letter of under score
          (?>
                  (?<B>   \[        )                   # match [
             |    (       [^\s\)\(+\-@\#$%\^&\*=`~,\\\|\[\]] )  # or anything that is not a space, +, @ etc..
          )*
          (?(B)                                         # if you match a bracket then:
              (
                 (?>
                          [^\[\]]
                       |    \[ (?<numberP>)                # balance match until opening ( = closing )
                       |    \] (?<-numberP>)
                  )*
                  \]
                  (?(numberP)(?!))
                  \.? 
              )
          )  # basically if you match a bracket keep selecting until you find even number of closing ]
        )
        +   # repeat this as many times as you can
      )
      (?(Q)(?!))   # Make regex fail if any of the following cases
      (?(C)(?!))
      (?(N)(?!))
      

      【讨论】:

        猜你喜欢
        • 2014-05-13
        • 1970-01-01
        • 2013-08-14
        • 2016-07-15
        • 2013-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多