智慧的光芒:来自IBM工程师的DSL解析器实现全揭秘

   今天看了一篇DSL解析器的设计实现的文章,感触颇深,其中的设计思想的确是很值得借鉴和学习的。

     一般思想:简单的概念(原子)通过组合手段可以形成复杂的概念,形成的复杂概念对组合手段来讲和简单的概念没有任何差别,这样,通过抽象手段,可以对新形成的复杂概念命名,把命名后的复杂概念当作简单概念通过组合手段,形成更加复杂的概念。

  即:三种机制来达成这个目标的:

  • 原子:语言中最简单、最基本的实体;
  • 组合手段:把原子组合起来构成更复杂实体的方法;
  • 抽象手段:命名复杂实体的方法,命名后的复杂实体可以和原子一样通过组合手段组合成为更复杂的实体。

根据该思想, 先构建解析器的原子,   原子解析器有2个,原子解析器1是直接将输入的字符串原样返回作为解析结果,其解析始终是成功。原子解析器2是,取出输入字符串的第一个字符作为解析结果,如果输入字符串是空,则解析失败。 原子解析器实现相同的解析器接口:

      interface Parser
{
    public Result parse(String target);
}

原子解析器1:

class Zero implements Parser 
{ 
    public Result parse(String target) { 
        return Result.succeed("", target); 
    } 
}
原子解析器2:
class Item implements Parser 
{ 
    public Result parse(String target) { 
        if(target.length() > 0) { 
            return Result.succeed(target.substring(0,1), 
                target.substring(1)); 
        } 
        return Result.fail(); 
    } 
} 
解析结果用一个类表示,其中包含解析是否成功的标志字段succeeded,已经完成解析的部分regcognized和剩余部分remaning。
其构造函数中设置已经解析部分,未解析部分和成功标志,其构造函数是私有构造函数,也就是说是无法通过其构造函数来得到该类的实例的,
该解析结果类通过public方法对外公开了获取解析状态,获取已解析部分和获取未解析部分的三个方法,public boolean is_succeeded() ,public String get_recognized() ,public String get_remaining() ;
同时,含有2个静态方法用于当解析成功或者失败时,得到结果实例。 
有了原子解析和解析结果的类, 现在就需要定义组合操作了,通过组合操作来组合上面定义的2个基本的原则解析器就可以得到复杂的解析器。
这几个组合子是:sat组合子,sat组合子将一个解析器与一个逻辑谓词组合封装在一起,形成一个新的解析器,该新的解析器会先用其包含的解析器来对输入进行解析,再判断解析的结果是否满足其定义的逻辑谓词,满足则成功,否则,则失败;
比如,如果用原子解析器2与逻辑谓词--是否是数字--来组合得到一个sat解析器的话,那么该sat解析器的
作用就是判断输入字符串的第一个字符是不是数字,是则解析成功,否则解析失败。因为逻辑谓词被抽象成了一个接口,通过对
该接口的不同实现,就可以得到不同的逻辑谓词,再拿这些不同的逻辑谓词的实现类作为参数,与原子解析器2组合,就可以得到不同的sat解析器用于判断输入字符串
的第一个字符是否满足每个特定的条件。
or组合子,or组合子将2个解析器了解起来,先用第一个解析器去解析输入字符串,如果成功直接返回,否则,用第二个解析器接着去解析,并且返回解析结果。
   seo组合子,把第一个解析器应用到目标字符串,如果成功,就把第二个解析器应用到第一个解析器识别后剩余的字符串上,如果这两个解析器都解析成功,那么由 SEQ 组合起来的这个复合解析器就解析成功,
只要有一个失败,复合解析器就解析失败。当解析成功时,其识别结果由这两个解析器的识别结果连接而成。
oneormore组合子,用于把某个解析器对输入字符串执行一次或者多次解析,每一个解析的输入都来自于上一次解析的输出。
  
通过对解析器的通用处理过程分析可以发现,不管是什么类型的解析器,其基本操作都是从输入字符串一个一个的取出字符,然后判断这些字符是否满足
一定的规范。 我们将这个过程细分,一个一个取字符,不管取多少个字符,其原子操作都是取一个字符,于是我们得到了原子解析器1;取出字符后,
都要判断是否满足一定的条件,通过将原子解析器2与谓词组合,形成sat组合子,可以用来判断字符串中单个字符是否满足某个条件,在此基础上,通过oneormore组合子包装,就可以
用来判断输入字符串的多个字符是否都满足某个条件,最后,再使用or组合子和seq组合子,就可以把多个解析器连接起来,这样就可以用来判断输入字符串中的
各个部分的多个字符是否都满足一定的条件。
  原子解析器1和原子解析器2实质上是取数原子操作,原子解析器1用于把输入字符串完全原封不动的取出,原子解析器2用于
将输入字符串的首字符取出。
   sat组合子实质上是一个判断原子操作,用于在前述操作基础上判断是否满足每个条件。 
   
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

walkingmanc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值