用于分析源代码的正则表达式

时间:2010-01-05 11:40:42

标签: c# regex

我有一个有趣的问题。我需要分析源代码并在编译之前确定变量的类型。所以,反射不能用!

只有五种类型:

double      x = 1.23;
long        x = 3;
string     s='Hello World!' 
bool        b=true 
object[]     A = [1, 1+2, 'Hello', s]

cource代码示例:

for (i=0; i < 5; i++)
{
    a=2;
    b=4;
    c=6;
    tesstClass.Str = 'sss';
}

我决定使用正则表达式来解决问题。

首先,我发现所有带有所需变量的代码(带有它的表达式)如下:

string pattern = variable + @"[\w.]*\s*[-*+/]?=\s*[\w\s+'*/-]*\s*;";
MatchCollection mc = Regex.Matches(code, pattern);

其次,我使用5个正则表达式(每种类型一个)分析每个匹配:

string stringPattern = @"'[^'\r\n]*'"; //String;
string doublePattern = @"\b[0-9]+\.[0-9]+\b"; //Double
string longPattern = @"[-+]?\b\d+\b"; // Integer with a sign
string boolPattern = @"\b(false|true)\b"; // Boolean
string arrayPattern = @"\[([\w']*\s*,?\s*)*\]"; // Array

我在正则表达式中非常糟糕。所以我定义了一组非常简单的r。表达式。你能帮我改进一下吗?

7 个答案:

答案 0 :(得分:2)

如果不是不可能使用正则表达式,那么您尝试做的事情非常困难,特别是因为您支持字符串结构。如果我这样做会发生什么:

a = 'b = 3;';

即。在这种情况下,您需要转义字符串以使正则表达式起作用。

在您能够执行任何有意义的分析之前,您确实需要对代码进行正确的解析。

答案 1 :(得分:2)

我也怀疑正则表达式适用于此。

正如Kragen所证明的,有些情况下正则表达式会匹配某些源代码,但它们会忽略源代码出现的上下文。这可能会导致错误。虽然可能可以为Kragen所展示的情况编写更智能的正则表达式,但它们很快就会变得非常复杂并且难以阅读/维护/理解,因为它们必须考虑许多不同的可能背景。 / p>

我更喜欢使用解析器生成器(例如Yacc或Bison)编写解析器。但是根据源代码的语言,这也可能非常棘手。

答案 2 :(得分:1)

准确找到什么?

您是否只需要找到文字(常量)或整个声明?可以使用表达式来查找文字,但解析整个代码会更复杂一些

给予语法机会

如果你必须解析所有代码......你知道语法分析器吗?当我学习'语言理论'时,我们使用语法来解析代码。您可以为令牌(常量,保留字,符号等)定义带正则表达式的基本分析器,并为所有结构使用语法分析器。

Java选项是JavaCC。必须有.Net选项。

基本上语法分析器可以解析复杂的结构(并且具有“记忆”)。 如果有限状态自动机等同于正则表达式,则具有堆栈的FSA(它是存储器)等同于语法。它具有更强的处理能力。

答案 3 :(得分:1)

执行此操作的常规方法是获取程序的AST,然后只需搜索所需的变量声明。建议的格式是产生这种AST的好方法。

但是,如果您需要动态分析程序,则无法使用此选项,因为您的代码可能有解析错误。在这种情况下,我感到痛苦......

您唯一的选择是解析源代码,正则表达式可能会有所帮助。

首先,我会从与此类似的正则表达式开始:

(double|long|string|bool|object)\s*(\[\s*\])?\s+(YOUR_VARIABLE_TOKEN)

obs:YOUR_VARIABLE_TOKEN缺失,因为该变量具有强大的定义规则,可以为每种语言构建它。

我没有测试这个正则表达式,它肯定不完美。这只是为了给你一个想法。

第二次,您必须使用某些异常情况验证这些匹配项。例如:

  1. 声明可能位于字符串文字内:"bool a;"
  2. 声明可能在评论中:/* bool a; */
  3. 此外,这不是一个非常奇怪的请求。 Eclipse在某些情况下也会进行此类评估,例如缩进。

    这不是一项容易的任务,特别是找到那些例外情况。祝你好运。

答案 4 :(得分:1)

鉴于这是.NET,您可以考虑使用CodeDOM来正确解析它。

使用预先存在的C# CodeDOM provider,使用Parse method获取源代码的结构化表示,然后遍历它。这使您可以创建一个可以适用于任何.NET语言的解决方案。

即使您说必须在编译之前完成,您也许可以使用临时的内存中编译,然后您可以使用反射进行处理。 CodeDOM提供商也可以帮助您。

答案 5 :(得分:0)

不要使用正则表达式。你正在做的是类型演绎,我猜你正在为学校做这件事。他们希望你学习另一种方式,比如逻辑统一。

你依赖的所有类型总是明显不同。如果为布尔值分配0或1怎么办?正则表达式不擅长减少输入。您的程序最多会生成每种类型的标识符列表。有更好的方法。

如果您处于商业环境中,您的解决方案将完全不可扩展,无法维护,不可靠且实施缓慢,因为您自己承认,这不是您的强项。

如果您不只是做作业,您应该可以访问该语言的解析器。如果不这样做,你应该使用解析器生成器(如Bison(或任何样式))启动它。

如果你正在做作业,我强烈建议你去看书。


编辑:我忘了说要怎么处理Bison:vP。您有每个变量的数据结构。它应该包含一组可能的类型。比如,unsigned int,其中一位代表每种类型,enum type_bits { double_bit = 1, long_bit = 2, string_bit = 4, … };。首先将所有位设置为1;即type_map = (type_bits) -1;。当您遇到每个操作时,屏蔽掉与其不兼容的位。完成后,您将设置一些位数。如果有多个规则,则应用优先规则,如果没有,则生成错误。

答案 6 :(得分:0)

您是否尝试过查看单个项目C#编译器的源代码,可能会有一些您觉得有用的想法。

svn co svn://anonsvn.mono-project.com/source/trunk/mcs

相关问题