2013-02-21 61 views
3

我想写一个简单解析器的嵌套块语法,只是分层明文。例如:最简单的嵌套块解析器

Some regular text. 
This is outputted as-is, foo{but THIS 
is inside a foo block}. 

bar{ 
    Blocks can be multi-line 
    and baz{nested} 
} 

最简单的方法是什么?我已经写了2个工作实现,但它们过于复杂。我尝试了全文正则表达式匹配和逐字符分析。

我必须向人们传授它的运作方式,所以简单是至关重要的。我不想介绍对Lex/Yacc Flex/Bison(或者PEGjs/Jison,实际上,这是javascript)的依赖。

回答

1

的不错的选择可能归结如下:

  • 鉴于你constaints,这将是递归下降。即使没有限制,这也是一个好方法。
  • 您可以分析char-by-char(传统)或编写使用本地字符串库的词法层来扫描{}。无论哪种方式,您可能都希望返回三个终端符号加上EOF:BLOCK_OF_TEXT,LEFT_BRACE和RIGHT_BRACE。
+0

是的,我去了递归下降。这可能需要一些解释来阐明这个概念,但在此之后,代码是非常可读的,流程是不言而喻的。 – slezica 2013-02-21 13:16:47

1
char c; 

    boolean ParseNestedBlocks(InputStream i) 
     { if ParseStreamContent(i) 
     then { if c=="}" then return false 
          else return true 
       } 
     else return false; 

    boolean ParseSteamContent(InputStream i) 
    { loop: 
     c = GetCharacter(i); 
     if c =="}" then return true; 
     if c== EOF then return true; 
     if c=="{" 
      { if ParseStreamContent(i) 
        { if c!="}" return false; } 
       else return false; 
      } 
     goto loop 
    } 
1

最近,我一直在使用解析器组合在纯JavaScript的一些项目。我将代码抽取到一个单独的项目中; you can find it here。这种方法类似于@DigitalRoss建议的递归下降解析器,但是在解析器特有的代码和一般解析器记账代码之间有更明确的分割。

一个适合您需求的解析器​​(如果我理解正确的您的要求)将是这个样子:

var open = literal("{"),     // matches only '{' 
    close = literal("}"),     // matches only '}' 
    normalChar = not1(alt(open, close)); // matches any char but '{' and '}' 

var form = new Parser(function() {}); // forward declaration for mutual recursion 

var block = node('block', 
       ['open', open  ], 
       ['body', many0(form)], 
       ['close', close  ]); 

form.parse = alt(normalChar, block).parse; // set 'form' to its actual value 

var parser = many0(form); 

,你会使用这样的:

// assuming 'parser' is the parser 
var parseResult = parser.parse("abc{def{ghi{}oop}javascript}is great"); 

的解析结果是一个语法树。

除了回溯,该库还可以帮助您在解析器调用之间生成漂亮的错误消息和线程用户状态。后两个我发现对于生成大括号错误消息非常有用,在出现以下情况时,报告问题以及出错的大括号标记的位置:1)有一个开放的大括号,但没有关闭; 2)存在不匹配的支具类型 - 即(...]{...); 3)没有匹配打开的近端大括号。

+0

这是一个非常美丽的抽象!你为什么不给它一些额外的文档工作,并将其制作成图书馆? – slezica 2013-02-22 19:06:06

+0

@uʍopǝpısdn谢谢!终于开始清理它了一下。 – 2013-03-26 14:23:32