解释器模式

时下一些产品会搞一些用处不大的功能来提高自己的逼格,而人工智能就成了一柄装逼利器。只要有点发飘的功能,就能冠以人工智能的名头。

 

之前做过一个产品,需要产品提供语音识别功能,根据用户口令执行相关操作,类似现在的智能音箱,只不过由于产品没有硬件,所以基于应用层的语音唤醒功能很蹩脚,唤醒功能咱先不讨论,那么语音识别功能又如何实现得呢,这个说起来就复杂了,你要先注册科大讯飞账号,然后掏钱,,,,咳咳,,,,,,扯远了,其实语音识别功能就是将用户语音识别成汉字,然后根据汉语日常语法进行解析,解析出高概率的命令,然后反馈给用户来确认,用户确认没问题,那就执行命令。例如我们预备匹配的一些动词(打开,启动,关闭等),以及我们的名词目标(控制面板,首页等),我们解析发现有这些动词名词的组合,然后和用户确认是否执行,否则其他的情况都标识并反馈为 “我没听清,你咬我啊”。

 

咱们再看看大话设计模式里面的那个例子,如果技术水平发展足够好,我们在未来可以设计出看着乐谱演奏音乐的机器人,它们会根据乐谱的文法规则对乐谱进行解析,并弹奏出美妙的旋律。

 

然后还有编译器,不同编程语言有不同的编译器,他们会根据语言的文法规则对高级语言进行翻译,翻译成机器可以识别的汇编指令,进一步实现程序的功能。而我们也可以做一个类似的简单编译器,用来将汉语语句或乐谱翻译成高级语言可识别的功能来执行。

 

其实以上所有例子都涉及到了同一种应用场景,就是需求给定了你一个语言,你要总结或定义出语言的文法,然后针对文法创造出一种解释器,解释给出的语句并执行相应操作,这就是我们所说的解释器模式,而解释器模式在编程中的典型应用就是正则表达式。

 

解释器模式:

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

 

我的理解:定义一个语言的文法,并定义一个解释器来解释该语言的句子。

 

一、名词解释

1、文法,百度连接 https://baike.baidu.com/item/%E6%96%87%E6%B3%95/8974691,其实我觉得就是语法,就是语言的组织规范,就是那些主谓宾定状补,好像啥时候学过。

 

二、特征

1、文法,我认为的即语法,若对既定语言进行解释翻译,那这个文法就需要咱们学习总结出来,若是自己创建一个语言,那么文法需要自己定义。

 

2、解释器,提供对语言的专门的解释翻译功能,这使得应用场景客户端不用在关注对语言的解释处理,通过封装实现了解耦,并且解释器可以进一步抽象,以实现文法的变化或增减。

 

三、作用,个人目前能想到的应用场景就是翻译,对上层的某些语言进行解释。

 

四、实现

 

又到了写例子的时候了,思来想去还是实现一个简单的正则表达式功能吧,毕竟很多应用场景里无法充分的展现出非终结符的作用,而正则大家都知道,更好理解一些。

我们把正则简化一些,假设正则里面就只有 [] {} * ? + () 这些文法规则,那么普通字符串就是终结符喽

 

//上下文

public class Context {

public String regular;

public String data;

}

 

//公共类

public class LoopResult {

public boolean result;

public int loopMin;

public int loopMax;

public LoopResult(boolean result,int min,int max)

{

this.result = result;

this.loopMin = min;

this.loopMax = max;

}

}

 

//解析循环次数

public class BasicFunction {

public LoopResult dealLoop(Context loopContext)

{

LoopResult result = new LoopResult(true,1,1);

if(loopContext.regular.startsWith("*"))

{

result.result = true;

result.loopMin = 0;

result.loopMax = -1;

loopContext.regular = loopContext.regular.substring(1);

}

else if(loopContext.regular.startsWith("+"))

{

result.result = true;

result.loopMin = 1;

result.loopMax = -1;

loopContext.regular = loopContext.regular.substring(1);

}

else if(loopContext.regular.startsWith("?"))

{

result.result = true;

result.loopMin = 0;

result.loopMax = 1;

loopContext.regular = loopContext.regular.substring(1);

}

else if(loopContext.regular.startsWith("{"))

{

if(loopContext.regular.indexOf('}') == -1)

{

result.result = false;

}

else

{

String stra = loopContext.regular.substring(0,loopContext.regular.indexOf('}')+1);

loopContext.regular = loopContext.regular.substring(loopContext.regular.indexOf('}')+1);

stra = stra.substring(1,stra.length()-1);

String[] aa = stra.split(",");

//{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。

if(aa.length == 1)

{

int nCount = 0;

if(stra.endsWith(","))

{

try

{

nCount = Integer.parseInt(aa[0]);

result.result = true;

result.loopMin = nCount;

result.loopMax = -1;

}

catch (NumberFormatException e)

{

result.result = false;

}

}

else

{

try

{

nCount = Integer.parseInt(aa[0]);

result.result = true;

result.loopMin = nCount;

result.loopMax = nCount;

}

catch (NumberFormatException e)

{

result.result = false;

}

}

}

//{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。

else if(aa.length ==2)

{

int nMin = 0,nMax = 0;

try

{

nMin = Integer.parseInt(aa[0]);

nMax = Integer.parseInt(aa[1]);

result.result = true;

result.loopMin = nMin;

result.loopMax = nMax;

}

catch (NumberFormatException e)

{

result.result = false;

}

}

}

}

else

{

}

return result;

}

 

}

 

//解释器接口

public abstract class Expression {

//实现对正则表达式的解释

public abstract boolean iterpreter(Context regular);

//实现匹配语句的功能

public abstract boolean match(Context data);

}

 

//语句规则

public class SentenceExpression extends Expression{

 

private List<Expression> list;

public SentenceExpression()

{

list = new ArrayList<Expression>();

}

@Override

public boolean iterpreter(Context regular) {

// TODO Auto-generated method stub

System.out.printf("[SentenceExpression::iterpreter] in,data:%s \n",regular.regular);

//语句初始不可能是 * + ? {}

if(regular.regular.startsWith("*")

|| regular.regular.startsWith("+")

|| regular.regular.startsWith("?")

|| regular.regular.startsWith("{") )

return false;

 

boolean result = true;

while(! regular.regular.isEmpty())

{

//如果为子语句文法规范

if(regular.regular.startsWith("("))

{

if(regular.regular.indexOf(")") > 1)

{

Expression es = new ParenthesesExpression();

if(! es.iterpreter(regular))

{

result = false;

break;

}

list.add(es);

}

else

{

result = false;

break;

}

}

//如果为中括号文法规范

else if(regular.regular.startsWith("["))

{

if(regular.regular.indexOf("]") > 1)

{

Expression es = new BracketExpression();

if(! es.iterpreter(regular))

{

result = false;

break;

}

list.add(es);

}

else

{

result = false;

break;

}

}

//如果为普通字符

else

{

Expression es = new TerminalExpression();

if(! es.iterpreter(regular))

{

result = false;

break;

}

list.add(es);

}

}

return result;

}

 

@Override

public boolean match(Context data) {

// TODO Auto-generated method stub

System.out.printf("[SentenceExpression::match] in,data:%s \n",data.data);

boolean result = true;

for(int i=0; i<list.size(); i++)

{

Expression ex = list.get(i);

if(! ex.match(data))

{

result = false;

break;

}

}

return result;

}

 

}

 

 

//终结符解释器,对于正则表达式来说,我认为就是普通字符串

public class TerminalExpression extends Expression {

 

private BasicFunction bf;

private String strData;

private char chLoop;

private int loopMin,loopMax;

public TerminalExpression()

{

bf = new BasicFunction();

strData = new String();

chLoop = 'a';

loopMin = 1;

loopMax = 1;

}

@Override

public boolean iterpreter(Context regular) {

// TODO Auto-generated method stub

System.out.printf("[TerminalExpression::iterpreter] in data:%s \n",regular.regular);

while(! regular.regular.isEmpty())

{

if(regular.regular.startsWith("*")

|| regular.regular.startsWith("+")

|| regular.regular.startsWith("?")

|| regular.regular.startsWith("{")

|| regular.regular.startsWith("[")

|| regular.regular.startsWith("("))

break;

strData = strData.concat(regular.regular.substring(0,1));

regular.regular = regular.regular.substring(1);

}

LoopResult ret = bf.dealLoop(regular);

if(! ret.result) return false;

loopMin = ret.loopMin;

loopMax = ret.loopMax;

chLoop = strData.charAt(strData.length()-1);

strData = strData.substring(0,strData.length()-1);

return true;

}

 

@Override

public boolean match(Context data) {

// TODO Auto-generated method stub

System.out.printf("[TerminalExpression::match] in,data:%s \n",data.data);

int nCount = 0;

if(! data.data.startsWith(strData))

return false;

data.data = data.data.substring(strData.length());

while(data.data.length() != 0)

{

if(data.data.charAt(0) == chLoop)nCount++;

else break;

data.data = data.data.substring(1);

}

boolean result = false;

if(loopMax < 0)

{

if(nCount >= loopMin) result = true;

else result = false;

}

else

{

if(nCount >= loopMin && nCount <= loopMax) result = true;

else result = false;

}

return result;

}

 

}

 

 

 

//根据()来解析子表达式语句

public class ParenthesesExpression extends Expression {

private BasicFunction bf;

private int loopMin,loopMax;

private Expression expression;

 

public ParenthesesExpression()

{

expression = new SentenceExpression();

bf = new BasicFunction();

loopMin = 1;

loopMax = 1;

}

@Override

public boolean iterpreter(Context regular) {

// TODO Auto-generated method stub

 

System.out.printf("[ParenthesesExpression::iterpreter] in,data:%s \n",regular.regular);

//如果开头结尾是一个(),那么证明是子语句

if(regular.regular.startsWith("("))

{

if(regular.regular.length() <= 2)

return false;

String strPh = regular.regular.substring(1, regular.regular.indexOf(')'));

regular.regular = regular.regular.substring(regular.regular.indexOf(')')+1);

LoopResult ret = bf.dealLoop(regular);

if(! ret.result) return false;

loopMin = ret.loopMin;

loopMax = ret.loopMax;

Context cc = new Context();

cc.regular = strPh;

if(! expression.iterpreter(cc))return false;

}

return true;

}

 

@Override

public boolean match(Context data) {

// TODO Auto-generated method stub

System.out.printf("[ParenthesesExpression::match] in,data:%s \n",data.data);

int nCount = 0;

while(expression.match(data))

{

nCount++;

}

boolean result = false;

if(loopMax < 0)

{

if(nCount >= loopMin) result = true;

else result = false;

}

else

{

if(nCount >= loopMin && nCount <= loopMax) result = true;

else result = false;

}

return result;

}

 

}

 

//[],例如[1-9],表示取任意1到9之间的一个数值(包括1和9)

public class BracketExpression extends Expression {

private BasicFunction bf;

private char chMin,chMax;

private int loopMin,loopMax;

public BracketExpression()

{

bf = new BasicFunction();

chMin = 0;

chMax = 0;

loopMin = 1;

loopMax = 1;

}

 

@Override

public boolean iterpreter(Context regular) {

System.out.printf("[BracketExpression::iterpreter] in,data:%s \n",regular.regular);

// TODO Auto-generated method stub

String strRe = regular.regular.substring(0,regular.regular.indexOf("]")+1);

strRe = strRe.substring(1,strRe.length()-1);

String[] aa = strRe.split("-");

if(aa.length != 2)return false;

if(aa[0].length()!=1 || aa[1].length()!=1 ) return false;

chMin = aa[0].charAt(0);

chMax = aa[1].charAt(0);

regular.regular = regular.regular.substring(regular.regular.indexOf("]")+1);

LoopResult ret = bf.dealLoop(regular);

if(! ret.result) return false;

loopMin = ret.loopMin;

loopMax = ret.loopMax;

return true;

}

 

@Override

public boolean match(Context data) {

// TODO Auto-generated method stub

System.out.printf("[BracketExpression::match] in,data:%s \n",data.data);

int nCount = 0;

while(data.data.charAt(0)>=chMin && data.data.charAt(0)<= chMax)

{

nCount++;

data.data = data.data.substring(1);

}

boolean result = false;

if(loopMax < 0)

{

if(nCount >= loopMin) result = true;

else result = false;

}

else

{

if(nCount >= loopMin && nCount <= loopMax) result = true;

else result = false;

}

return result;

}

 

}

 

 

//应用场景

public class Client {

 

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

// [] {} * ? + ()

Context context = new Context();

context.regular = "abc*[d-g]?([h-n]{1,9}opqrst)uvwxyz+";

context.data = "ablopqrstuvwxyz";

Expression exp = new SentenceExpression();

if(! exp.iterpreter(context))

{

System.out.println("mother fuck!");

return:

}

else

{

System.out.println("yes baby!");

}

if(! exp.match(context))

{

System.out.println("mother fuck!");

}

else

{

System.out.println("yes baby!");

}

}

}

 

 

给出的例子是为了阐述解释器模式的使用方法,代码存在很多漏洞,不可以仔细推敲,如果您发现了代码的漏洞想找我理论,哈哈,怎么可能,我不会留联系方式的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值