最近我们的团队希望建立自己的查询语言,但我们遇到了关于regexp
的问题如果我们在下面有查询
select A where B skip C limit D
关键字“where”,“skip”和“limit”可以有1或0,这意味着我们也可以有一个像
这样的查询select A where B skip C
select A skip C limit D
select A limit D
重点是我们想知道是否可以定义一个可以匹配此查询并捕获A,B,C和D的“单个”正则表达式?
这是我们现在的工作方式......
dql_parser.parse = function(str) {
var reg_arr = []
if(str.toLowerCase().indexOf('select') !== -1) {
var reg = new RegExp(/select\s+(.*?)(limit|where|skip)/i)
var exe = reg.exec(str)
if(exe !== null) {
reg_arr.push('fields=' + exe[1])
}else {
var reg = new RegExp(/select\s+(.*)?/i)
var exe = reg.exec(str)
reg_arr.push('fields=' + exe[1])
}
}
if(str.toLowerCase().indexOf('where') !== -1) {
var reg = new RegExp(/where\s+(.*?)(select|limit|skip)/i)
var exe = reg.exec(str)
if(exe !== null) {
reg_arr.push('selector=' + exe[1])
}else {
var reg = new RegExp(/where\s+(.*)?/i)
var exe = reg.exec(str)
reg_arr.push('selector=' + exe[1])
}
}
if(str.toLowerCase().indexOf('skip') !== -1) {
var reg = new RegExp(/skip\s+(.*?)(select|limit|where)/i)
var exe = reg.exec(str)
if(exe !== null) {
reg_arr.push('skip=' + exe[1])
}else {
var reg = new RegExp(/skip\s+(.*)?/i)
var exe = reg.exec(str)
reg_arr.push('skip=' + exe[1])
}
}
if(str.toLowerCase().indexOf('limit') !== -1){
var reg = new RegExp(/limit\s+(.*?)(select|where|skip)/i)
var exe = reg.exec(str)
if(exe !== null) {
reg_arr.push('limit=' + exe[1])
}else {
var reg = new RegExp(/limit\s+(.*)?/i)
var exe = reg.exec(str)
reg_arr.push('limit=' + exe[1])
}
}
return reg_arr;
}
任何建议都表示赞赏。
答案 0 :(得分:3)
这不是您问题的直接答案,但可能有所帮助。
我建议您使用PEG:解析器生成器。 您将在看起来像BNF的东西中定义您的语言,然后它将为您生成解析器。
这是一个非常可靠的工具,比regexp强大得多,并且非常容易使用,特别是对于像你这样的简单DSL。
答案 1 :(得分:1)
长答案
您想“设计自己的查询语言”,并决定使用RegEx ???
进行解析嗯...... 没有。
编写一个“真正的”解析器是唯一的方法,如果你不能应对挑战,也许你应该放弃这个想法。
如果你真的想这样做,那么先研究一下Flex and Bison(Lex / Yacc,老实说,我不知道他们叫什么了)。这是真正的交易(至少这是我的首选工具包,如果你“投资”它,从长远来看肯定会付出代价。)
祝你好运! ; - )答案 2 :(得分:0)
但如果你真的,在你的日子里真的想要这样的痛苦:
(select\s+(\w*))\s+(where\s+(\w*))?\s*(skip\s+(\w*))?\s*(limit\s+(\w*))?
会给你A,B C和D. 祝你好运!