查找JavaScript表达式的部分
假设我有一个JavaScript表达式作为字符串,如下所示:查找JavaScript表达式的部分,javascript,regex,expression,conditional-statements,Javascript,Regex,Expression,Conditional Statements,假设我有一个JavaScript表达式作为字符串,如下所示: string = ' collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]' 现在我需要得到这个表达式的一些部分,它们是我所做工作的“依赖项” 这就是我需要从字符串中提取的内容 result = [ 'collections.users[ currentUsers[ ids[1].id ] ]',
string = ' collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]'
现在我需要得到这个表达式的一些部分,它们是我所做工作的“依赖项”
这就是我需要从字符串中提取的内容
result = [
'collections.users[ currentUsers[ ids[1].id ] ]',
'currentUsers[ ids[1].id]', 'ids[1].id',
'users[ ids[1].id ]', 'ids[1].id'
]
它基本上需要每个包含[*]
的“变量”
这是每一个可能导致表达式改变的变量,我已经尝试了大约3天了,到目前为止,我尝试了但失败了
由于问题的性质,我将给50+赏金提供最佳答案/建议您可能需要使用递归函数并迭代每个字符。每次你点击一个开放的括号,你就会进入一个新的递归层;每次你击中一个较近的支架,你就退出一个 我相信这正是你想要的
var toParse = 'collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]';
var operators = ['&','|','+','-','=','/','*'];
var answer = [];
parseBrackets(0);
function parseBrackets(start) {
var openBrackets = 0;
var currentString = '';
for (var i = start; i < toParse.length; i++) {
if (toParse[i] == '[') { // open bracket
if (openBrackets == 0) {
parseBrackets(i + 1);
}
currentString += toParse[i];
openBrackets++;
} else if (toParse[i] == ']' && openBrackets-- == 0) { // close bracket
answer.push(currentString);
return;
} else if (operators.indexOf(toParse[i]) >= 0) { // this is an expression operator, don't include it
if (currentString != '') {
answer.push(currentString);
}
currentString = '';
} else { // add this character to the current string
currentString += toParse[i];
}
}
answer.push(currentString); // add the current string to the list of parsed 'dependencies'
}
console.log(answer);
Regexp不适合这个问题,因为Regexp不能“计数”。也就是说,无论您的regexp有多复杂,都会有一些不被接受的括号嵌套级别 您真正需要的是一个解析器。有些解析器生成器使用语法规则生成代码。这里有一些: 你的规则看起来很简单。大概是这样的:
Expression = AnythingExceptBrackets '[' Expression ']' AnythingExceptBrackets
| AnythingExceptBrackets
AnythingExceptBrackets = [^\\[\\]]+
当您获得生成器时,剩下的唯一一步就是将已识别的标记粘贴到结果数组中。为了成功解析短语,必须知道短语的完整结构。不可能从给出的一个例子中确定所有可能的结构。然而,在做出一些假设后,我使用扩展的Backus–Naur表单(EBNF)定义了一个可能的结构 假设每个数组元素可以有一个整数、一个变量或另一个数组元素作为索引,变量和数组元素可以有使用点表示法编写的属性。数组元素列表之间可以有运算符 然后,您可以根据需要修改和扩展此结构 扩展巴科斯-诺尔形式表示法 {}0或更多 []1个或更多 ()组 letter=“a”|“b”|“c…”“x”|“y”|“z”|“a”|“b”|“…”|“y”|“z” 数字=0“|”1“|”2“|”3“|”4“|”5“|”6“|”7“|”8“|”9 整数=[位数] 术语=[字符|位] 标识符=($| |字符){term} 属性=.char{term} 变量=标识符{property} 索引=数字|变量|数字 数组=变量“[”索引“]”{property} 运算符=“&&&”|“|”|+“|”-“|”*“|”/” 短语=数组{运算符数组}: 有一个解析短语并生成给定示例结果的 代码是
letter = /[a-zA-Z]/;
digit = /[0-9]/;
join = /[&|+\-*]/; //possible operators
var phrase=' collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]';
var ptr=0;
var stack=[];
phrase=phrase.replace(/\s/g,''); //remove extraneous white space
phrase+=':'; //add : as terminator
var crctr=readNext();
getArray();
document.getElementById('results').innerHTML=setResults();
function getArray() {
var L=new List();
L.name=getVariable();
L.index=getIndex();
crctr=readNext();
if(crctr=='.') {
crctr=readNext();
L.property=getProperty();
}
stack.push(L);
if(crctr !=':') { //not end of phrase
if (join.test(crctr)) {
readJoin();
getArray();
}
}
}
function getIndex() {
var indx='';
if(crctr=="[") {
crctr=readNext();
if(digit.test(crctr))
{
indx=getInteger();
if(crctr==']') {
return indx;
}
}
else {
indx=getVariable();
if(crctr=="]"){
return indx;
}
else if(crctr=="[") {
var L=new List();
L.name=indx;
L.index=getIndex();
crctr=readNext();
if(crctr=='.') {
crctr=readNext();
L.property=getProperty();
}
stack.push(L);
return L;
}
}
}
else {
throw 'index error';
}
}
function getVariable() {
var v="";
if(crctr=="$" || crctr=="_" || letter.test(crctr)) {
v+=crctr;
crctr=readNext();
v+=getIdentifier();
if (crctr==".") {
v+=crctr;
crctr=readNext();
v+=getProperty();
}
return v;
}
else {
throw 'variable error';
}
}
function getIdentifier() {
var id="";
if(crctr=="$" || crctr=="_" || letter.test(crctr)) {
id=crctr;
crctr=readNext();
id+=getTerm();
return id;
}
else {
throw 'Identifier error';
}
}
function getTerm() {
var t="";
while(letter.test(crctr) || digit.test(crctr)) {
t+=crctr;
crctr=readNext();
}
return t;
}
function getProperty() {
var p='';
if(letter.test(crctr)) {
p=crctr;
crctr=readNext();
while(letter.test(crctr) || digit.test(crctr)) {
p+=crctr;
crctr=readNext();
}
if(crctr=='.') {
p+=crctr;
crctr=readNext();
p+=getProperty();
}
else {
return p;
}
}
else {
throw 'property error';
}
}
function getInteger() {
var i='';
while(digit.test(crctr)) {
i+=crctr;
crctr=readNext();
}
return i;
}
function readJoin() {
if(crctr=="&" || crctr=="|") {
crctr=readNext();
}
crctr=readNext();
}
function readNext(){
var crctr=phrase.charAt(ptr);
ptr+=1;
return crctr;
}
function List() {
this.name='';
this.index='';
this.property='';
}
function setResults() {
var r='results = [';
while(stack.length>1) {
var A=stack.pop();
r+='<br> '+listArrays(A)+',';
}
var A=stack.pop();
r+='<br> '+listArrays(A);
return r+='<br>]';
}
function listArrays(A) {
if(A.index.name) { //A.index is array
var name=A.name;
var indx=A.index;
var prp='';
if(A.property !='') {
prp='.'+A.property;
}
return A.name+'['+listArrays(A.index)+']'+prp;
}
else {
var name=A.name;
var indx=A.index;
var prp='';
if(A.property !='') {
prp='.'+A.property;
}
return A.name+'['+A.index+']'+prp;
}
}
字母=/[a-zA-Z]/;
数字=/[0-9]/;
join=/[&+\-*]/;//可能的运算符
变量短语='collections.users[currentUsers[ids[1].id]]和&users[ids[1].id]';
var-ptr=0;
var堆栈=[];
短语=短语。替换(//\s/g',);//删除多余的空白
短语+=':';//添加:作为终止符
var crctr=readNext();
getArray();
document.getElementById('results')。innerHTML=setResults();
函数getArray(){
var L=新列表();
L.name=getVariable();
L.index=getIndex();
crctr=readNext();
如果(crctr=='。){
crctr=readNext();
L.property=getProperty();
}
堆栈推送(L);
如果(crctr!=':'){//不是短语的结尾
if(join.test(crctr)){
readJoin();
getArray();
}
}
}
函数getIndex(){
var indx='';
如果(crctr==“[”){
crctr=readNext();
if(数字测试(crctr))
{
indx=getInteger();
如果(crctr==']'){
返回indx;
}
}
否则{
indx=getVariable();
如果(crctr==“]”){
返回indx;
}
如果(crctr==“[”){
var L=新列表();
L.name=indx;
L.index=getIndex();
crctr=readNext();
如果(crctr=='。){
crctr=readNext();
L.property=getProperty();
}
堆栈推送(L);
返回L;
}
}
}
否则{
抛出“索引错误”;
}
}
函数getVariable(){
var v=“”;
如果(crctr==“$”|| crctr==“|”字母测试(crctr)){
v+=crctr;
crctr=readNext();
v+=getIdentifier();
如果(crctr==”){
v+=crctr;
crctr=readNext();
v+=getProperty();
}
返回v;
}
否则{
抛出“变量错误”;
}
}
函数getIdentifier(){
var id=“”;
如果(crctr==“$”|| crctr==“|”字母测试(crctr)){
id=crctr;
crctr=readNext();
id+=getTerm();
返回id;
}
否则{
抛出“标识符错误”;
}
}
函数getTerm(){
var t=“”;
while(字母测试(crctr)| |数字测试(crctr)){
t+=crctr;
crctr=readNext();
}
返回t;
}
函数getProperty(){
var p='';
if(字母测试(crctr)){
p=crctr;
crctr=readNext();
while(字母测试(crctr)| |数字测试(crctr)){
p+=crctr;
crctr=readNext();
}
letter = /[a-zA-Z]/;
digit = /[0-9]/;
join = /[&|+\-*]/; //possible operators
var phrase=' collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]';
var ptr=0;
var stack=[];
phrase=phrase.replace(/\s/g,''); //remove extraneous white space
phrase+=':'; //add : as terminator
var crctr=readNext();
getArray();
document.getElementById('results').innerHTML=setResults();
function getArray() {
var L=new List();
L.name=getVariable();
L.index=getIndex();
crctr=readNext();
if(crctr=='.') {
crctr=readNext();
L.property=getProperty();
}
stack.push(L);
if(crctr !=':') { //not end of phrase
if (join.test(crctr)) {
readJoin();
getArray();
}
}
}
function getIndex() {
var indx='';
if(crctr=="[") {
crctr=readNext();
if(digit.test(crctr))
{
indx=getInteger();
if(crctr==']') {
return indx;
}
}
else {
indx=getVariable();
if(crctr=="]"){
return indx;
}
else if(crctr=="[") {
var L=new List();
L.name=indx;
L.index=getIndex();
crctr=readNext();
if(crctr=='.') {
crctr=readNext();
L.property=getProperty();
}
stack.push(L);
return L;
}
}
}
else {
throw 'index error';
}
}
function getVariable() {
var v="";
if(crctr=="$" || crctr=="_" || letter.test(crctr)) {
v+=crctr;
crctr=readNext();
v+=getIdentifier();
if (crctr==".") {
v+=crctr;
crctr=readNext();
v+=getProperty();
}
return v;
}
else {
throw 'variable error';
}
}
function getIdentifier() {
var id="";
if(crctr=="$" || crctr=="_" || letter.test(crctr)) {
id=crctr;
crctr=readNext();
id+=getTerm();
return id;
}
else {
throw 'Identifier error';
}
}
function getTerm() {
var t="";
while(letter.test(crctr) || digit.test(crctr)) {
t+=crctr;
crctr=readNext();
}
return t;
}
function getProperty() {
var p='';
if(letter.test(crctr)) {
p=crctr;
crctr=readNext();
while(letter.test(crctr) || digit.test(crctr)) {
p+=crctr;
crctr=readNext();
}
if(crctr=='.') {
p+=crctr;
crctr=readNext();
p+=getProperty();
}
else {
return p;
}
}
else {
throw 'property error';
}
}
function getInteger() {
var i='';
while(digit.test(crctr)) {
i+=crctr;
crctr=readNext();
}
return i;
}
function readJoin() {
if(crctr=="&" || crctr=="|") {
crctr=readNext();
}
crctr=readNext();
}
function readNext(){
var crctr=phrase.charAt(ptr);
ptr+=1;
return crctr;
}
function List() {
this.name='';
this.index='';
this.property='';
}
function setResults() {
var r='results = [';
while(stack.length>1) {
var A=stack.pop();
r+='<br> '+listArrays(A)+',';
}
var A=stack.pop();
r+='<br> '+listArrays(A);
return r+='<br>]';
}
function listArrays(A) {
if(A.index.name) { //A.index is array
var name=A.name;
var indx=A.index;
var prp='';
if(A.property !='') {
prp='.'+A.property;
}
return A.name+'['+listArrays(A.index)+']'+prp;
}
else {
var name=A.name;
var indx=A.index;
var prp='';
if(A.property !='') {
prp='.'+A.property;
}
return A.name+'['+A.index+']'+prp;
}
}