2013-03-20 69 views
0

我正在写,将在自定义语言(对C语法和Allman style格式基于略有)解析一个脚本的应用程序,并正在寻找一个更好的(阅读:快)解析块的方式的脚本代码转换为字符串数组的方式比我目前做的方式(当前的方法可以,但更多的是调试比其他任何东西)。解析脚本在C#循环

脚本内容当前从文件读取到字符串数组并传递给方法。

以下脚本块模板:

loop [/* some conditional */ ] 
{ 
    /* a whole bunch of commands that are to be read into 
    * a List<string>, then converted to a string[] and 
    * passed to the next step for execution */ 

    /* some command that has a bracket delimited set of 
    * properties or attributes */ 
    { 
    /* some more commands to be acted on */ 
    } 
} 

基本上,花括号块可以被嵌套(就像在任何其他基于C语言),我正在寻找找到个人的最好方式像这样的块。

的大括号分隔块将ALWAYS格式化这样的 - 开括号后的括号中的内容将开始就行和随后将最终的属性/命令/注释之后的行的支架/随你。

一个例子可能是:

loop [ someVar <= 10 ] 
{ 
    informUser "Get ready to do something" 
    readValue 
    { 
    valueToLookFor = 0x54 
    timeout = 10 /* in seconds */ 
    } 
} 

这将告诉应用程序循环,同时someVar小于10(抱歉吸吮鸡蛋评论)。每一次,我们都会向用户传递一条消息,并从某处寻找特定值(超时时间为10秒)。

这里是我如何做它在一分钟(注:调用此经过整个字符串[]包含当前脚本到它与指数从读法):

private string[] findEntireBlock(string[] scriptContents, int indexToReadFrom, 
           out int newIndex) 
{ 
    newIndex = 0; 
    int openBraceCount = 0;  // for '{' char count 
    int closeBraceCount = 0; // for '}' char count 
    int openSquareCount = 0; // for '[' char count 
    int closeSquareCount = 0; // for ']' char count 

    List<string> fullblock = new List<string>(); 

    for (int i = indexToReadFrom; i < scriptContents.Length; i++) 
    { 
     if (scriptContents[i].Contains('}')) 
     { 
      if (scriptContents[i].Contains("[") && fullblock.Count > 0) 
      { 
       //throw new exception, as we shouldn't expect to 
       //to find a line which starts with [ when we've already 
      } 
      else 
      { 
       if (scriptContents[i].Contains('{')) openBraceCount++; 
       if (scriptContents[i].Contains('}')) closeBraceCount++; 
       if (scriptContents[i].Contains('[')) openSquareCount++; 
       if (scriptContents[i].Contains(']')) closeBraceCount++; 
       newIndex = i; 
       fullblock.Add(scriptContents[i]); 
       break; 
      } 
     } 
     else 
     { 
      if (scriptContents[i].Contains("[") && fullblock.Count > 0) 
      { 
       //throw new exception, as we shouldn't expect to 
       //to find a line which starts with [ when we've already 
      } 
      else 
      { 
       if (scriptContents[i].Contains('{')) openBraceCount++; 
       if (scriptContents[i].Contains('}')) closeBraceCount++; 
       if (scriptContents[i].Contains('[')) openSquareCount++; 
       if (scriptContents[i].Contains(']')) closeBraceCount++; 
       fullblock.Add(scriptContents[i]); 
      } 
     } 
    } 
    if (openBraceCount == closeBraceCount && 
     openSquareCount == closeSquareCount) 
      return fullblock.ToArray(); 
    else 
     //throw new exception, the number of open brackets doesn't match 
     //the number of close brackets 
} 

我同意这可能是一个稍微迟钝和缓慢的方法,这就是为什么我要求任何想法如何重新实现这个速度和清晰度(如果能够达到平衡,那是)。

我在寻找远离RegEx的地方,因为我不能用它来维护支架数量,而且我不确定您是否可以编写RegEx语句(这是正确的术语?),可以递归地行动。我正在考虑从内部向外工作,但我相信这会很慢。

我是不是寻找有人为我重写它,但是我可以使用的算法或技术/库的一般想法会改进我的方法。

作为一个问题,编译器如何处理源代码中的多个嵌套括号?

+1

查看语法,词法分析器和解析器。他们是你需要解析的工具。 – 2013-03-20 10:35:53

+0

在我回顾一下Let's Build a Compiler后,我会在[Andrew Cooper](http://stackoverflow.com/users/377639/andrew-cooper)的回答中回答他的回答 – 2013-03-22 09:34:27

回答

3

Let's Build a Compiler,作者:Jack Crenshaw,对于构建一个基本的编译器来说是一个非常好用,易于阅读的介绍。所讨论的技术应该有助于你在这里尝试做什么。

+0

我会重点检查一下,并尝试从中获取技巧。但我担心花时间阅读大量文章。不过,我仍然会这样做。感谢您的链接 – 2013-03-22 09:32:55