解析表达式的问题

od 2004-09-13 01:33:46
怎么解析该表达式?比如说:
([asdf,123,ccc]∧[da,43,aaa]) ∨ ([fd,324,ddd]∧[asdf,43,eee])...
而且每个字段都是从数据库中取出的,还要判断它们的正确性,错误的时候报出错地点(这个问题可以先不解决)

二叉树?编译原理?正则表达式?学了也是白学,这个问题实在解决不了了
xdjm们帮忙呀!

如果问题解决还可去此帖处领另外的100分:
http://community.csdn.net/Expert/topic/3367/3367036.xml?temp=.5583155

...全文
336 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
registered 2004-09-15
  • 打赏
  • 举报
回复

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* A class for evaluate certain expression.
*/
public class Evaluator2 {
private Pattern[] correct_exp = {
Pattern.compile("\\[(.+?)\\](?!\\])"),
Pattern.compile("\\w++,\\w++,\\w++,(?i:(true)|(false))"),
};

private Pattern unit = Pattern.compile("\\[\\w++,\\w++,\\w++,(\\w++)\\]");

private Pattern[] exp_p = {
Pattern.compile("\\((?!\\()([\\d&|]++)\\)"),
Pattern.compile("(\\d++)([&])(\\d++)"),
Pattern.compile("(\\d++)([|])(\\d++)"),
};

private int count;

private ArrayList list = new ArrayList(64);


/**
* Check expression unit correctness.
*
* @param exp
* @return
*/
private boolean isCorrect(String exp) {
int count_unit = 1;
int count_error = 1;
boolean correct = true;
String error_msg = "\n";
Matcher m1 = correct_exp[0].matcher(exp);
Matcher m2 = correct_exp[1].matcher(exp);

while (m1.find()) {
m2.reset(m1.group(1));
if (!m2.matches()) {
error_msg += "Error " + count_error +
": unit " + count_unit + " \"" + m1.group(0) + "\"\n";
count_error++;
correct = false;
}
count_unit++;
}

if (!correct) {
throw new IllegalArgumentException(error_msg);
}

return correct;
}

/**
* Prepare internal expression.
*
* @param exp
* @return
*/
private String prepare(String exp) {
Matcher m = unit.matcher(exp);
StringBuffer sbuff = new StringBuffer();

list.clear();
while (m.find()) {
m.appendReplacement(sbuff, String.valueOf(count));
list.add(count, Boolean.valueOf(m.group(1)));
count++;
}
m.appendTail(sbuff);

return sbuff.toString();
}

private Boolean and(Boolean b1, Boolean b2) {
return new Boolean(b1.booleanValue() && b2.booleanValue());
}

private Boolean or(Boolean b1, Boolean b2) {
return new Boolean(b1.booleanValue() || b2.booleanValue());
}

/**
* Evaluate expression.
*
* @param exp
* @return
*/
public Boolean evaluate(String exp) {
Matcher m;

isCorrect(exp);

count = 0;
list.clear();
exp = prepare(exp);
//System.out.println("exp = " + exp);

for (int i = 0; i < 3; i++) {
m = exp_p[i].matcher(exp);
for (; m.find(); count++) {
list.add(count, eva(m.group(0)));
exp = m.replaceFirst(String.valueOf(count));
m.reset(exp);
}
}

return (Boolean) list.get(count - 1);
}

/**
* Evaluate sub expression.
*
* @param sub_exp
* @return
*/
private Boolean eva(String sub_exp) {
int operand_l;
int operand_r;
Matcher m;

//System.out.println("exp = " + sub_exp);
for (int i = 1; i < 3; i++) {
m = exp_p[i].matcher(sub_exp);
for (; m.find(); count++) {
operand_l = Integer.parseInt(m.group(1));
operand_r = Integer.parseInt(m.group(3));
if (m.group(2).equals("&")) {
list.add(count, and((Boolean) list.get(operand_l),
(Boolean) list.get(operand_r)));
} else {
list.add(count, or((Boolean) list.get(operand_l),
(Boolean) list.get(operand_r)));
}
sub_exp = m.replaceFirst(String.valueOf(count));
m.reset(sub_exp);
}
//System.out.println("exp = " + sub_exp);
}

return (Boolean) list.get(count - 1);
}


public static void main(String[] args) {
/* Do NOT allow spaces! */
String example = "([c,c,c,true]]&[[[c,c,c,false]]]|[c,c,c,true])" +
"&[c,c,c,true]&([c,c,c,falSe]]|[[c,c,c,true])";
/*String example = "([c,c,c,true]&[c,c,c,false]|[c,c,c,true])" +
"&[c,c,c,true]&([c,c,c,falSe]|[c,c,c,true])";*/
Evaluator2 e = new Evaluator2();

try {
System.out.println(e.evaluate(example));
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
}
}

这个只能发现[](单元)内的错误, 无法发现()&|等错误
正句语法检查你先前说不属于问题范围内所以没有做
od 2004-09-15
  • 打赏
  • 举报
回复
多谢你这两天的帮忙,问题基本已经解决
如果你有兴趣的话可以用不同的方法来把这个帖子完善了,程序写健全一些,
我把我的方法完善后也贴上,然后再把这个帖子结了.我想借这个机会把学过的东西都用一用^_^如果没时间的话就通知我一声,我马上结
你去数据结构留个脚印吧,我先结了它.谁说java版怎么怎么了,解决问题还是要来这里^_^
od 2004-09-15
  • 打赏
  • 举报
回复
呵呵~~~我昨天也连讲三句就不让我再讲了,烦劳"大厅"帮忙^_^
od 2004-09-14
  • 打赏
  • 举报
回复
([asdf,123,ccc]∧[da,43,aaa]) ∨ ([fd,324,ddd]∧[asdf,43,eee])... 如果解析后格式正确的话,经处理会在子节点加一个字段true或false,变成这样的形式:
([asdf,123,ccc,true]∧[da,43,aaa,false]) ∨ ([fd,324,ddd,true]∧[asdf,43,eee,false])...

然后再解析为
if("(true && false) || (true && false)... ")
{
...
}
else...

也就是说在保证子节点[asdf,123,ccc]格式正确的前提下,再保证替换子节点后的"(true && false) || (true && false)... "格式正确
takecare 2004-09-14
  • 打赏
  • 举报
回复
这个偶不熟悉,向你们学习!
od 2004-09-14
  • 打赏
  • 举报
回复
总结一下:
解析是从([asdf,123,ccc]∧[da,43,aaa]) ∨ ([fd,324,ddd]∧[asdf,43,eee])... 开始的
是数据库中读出的数据,并且与或组合以及()不固定,但子节点:[asdf,123,ccc]的格式是固定的!

最终结果是boolean型
od 2004-09-14
  • 打赏
  • 举报
回复
还有,("(true && false) || (true && false)... ")并不是固定格式的

个数,组合方式都是根据具体情况生成的
od 2004-09-14
  • 打赏
  • 举报
回复
registered(已注册)

真是太不好意思了,我的问题表达的太不清楚了!
([asdf,123,ccc]∧[da,43,aaa]) ∨ ([fd,324,ddd]∧[asdf,43,eee])...
这个是初始生成的,在我的程序里最终每个[]中的内容都会被转换成true或者是false

最终要生成这样的式子:
if("(true && false) || (true && false)... ")
{
...
}
else...
要保证if()中的String格式正确并且最终可以被解析成boolean型

感觉要做健壮太难了,要check的东西太多太多......
registered 2004-09-14
  • 打赏
  • 举报
回复
如果说解决方案还是编译原理中用的方法好(后缀表达式求值法)
但是那个实现起来费时费力, 所以这里用了一个折中的方法
此方法虽然把功能都实现了, 但是大批量操作起来性能比较差
将就着用吧...
registered 2004-09-14
  • 打赏
  • 举报
回复
有个疏忽
你用的时候把 evaluate 方法改成 public
registered 2004-09-14
  • 打赏
  • 举报
回复

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* A class for evaluate certain expression.
*/
public class Evaluator2 {
private Pattern[] correct_exp = {
Pattern.compile("\\[(.+?)\\]"),
Pattern.compile("\\w++,\\w++,\\w++,(?i:(true)|(false))"),
};

private Pattern unit = Pattern.compile("\\[\\w++,\\w++,\\w++,(\\w++)\\]");

private Pattern[] exp_p = {
Pattern.compile("\\((?!\\()([\\d&|]++)\\)"),
Pattern.compile("(\\d++)([&])(\\d++)"),
Pattern.compile("(\\d++)([|])(\\d++)"),
};

private int count;

private ArrayList list = new ArrayList(64);


/**
* Check expression unit correctness.
*
* @param exp
* @return
*/
private boolean isCorrect(String exp) {
Matcher m1 = correct_exp[0].matcher(exp);
Matcher m2 = correct_exp[1].matcher(exp);

while (m1.find()) {
m2.reset(m1.group(1));
if (!m2.matches()) {
return false;
}
}

return true;
}

/**
* Prepare internal expression.
*
* @param exp
* @return
*/
private String prepare(String exp) {
Matcher m = unit.matcher(exp);
StringBuffer sbuff = new StringBuffer();

list.clear();
while (m.find()) {
m.appendReplacement(sbuff, String.valueOf(count));
list.add(count, Boolean.valueOf(m.group(1)));
count++;
}
m.appendTail(sbuff);

return sbuff.toString();
}

private Boolean and(Boolean b1, Boolean b2) {
return new Boolean(b1.booleanValue() && b2.booleanValue());
}

private Boolean or(Boolean b1, Boolean b2) {
return new Boolean(b1.booleanValue() || b2.booleanValue());
}

/**
* Evaluate expression.
*
* @param exp
* @return
*/
private Boolean evaluate(String exp) {
Matcher m;

if (!isCorrect(exp)) {
return null;
}

count = 0;
list.clear();
exp = prepare(exp);
//System.out.println("exp = " + exp);

for (int i = 0; i < 3; i++) {
m = exp_p[i].matcher(exp);
for (; m.find(); count++) {
list.add(count, eva(m.group(0)));
exp = m.replaceFirst(String.valueOf(count));
m.reset(exp);
}
}

return (Boolean) list.get(count - 1);
}

/**
* Evaluate sub expression.
*
* @param sub_exp
* @return
*/
private Boolean eva(String sub_exp) {
int operand_l;
int operand_r;
Matcher m;

//System.out.println("exp = " + sub_exp);
for (int i = 1; i < 3; i++) {
m = exp_p[i].matcher(sub_exp);
for (; m.find(); count++) {
operand_l = Integer.parseInt(m.group(1));
operand_r = Integer.parseInt(m.group(3));
if (m.group(2).equals("&")) {
list.add(count, and((Boolean) list.get(operand_l),
(Boolean) list.get(operand_r)));
} else {
list.add(count, or((Boolean) list.get(operand_l),
(Boolean) list.get(operand_r)));
}
sub_exp = m.replaceFirst(String.valueOf(count));
m.reset(sub_exp);
}
//System.out.println("exp = " + sub_exp);
}

return (Boolean) list.get(count - 1);
}


public static void main(String[] args) {
/* Do NOT allow spaces! */
String example = "([c,c,c,true]&[c,c,c,false]|[c,c,c,true])" +
"&[c,c,c,true]&([c,c,c,false]|[c,c,c,true])";
Evaluator2 e = new Evaluator2();
System.out.println(e.evaluate(example));
}
}

你再测试测试
od 2004-09-14
  • 打赏
  • 举报
回复
最好明天晚上以前
registered 2004-09-14
  • 打赏
  • 举报
回复
Mastering Regular Expressions
http://www.amazon.com/exec/obidos/ASIN/1565922573/qid%3D1020015647/sr%3D1-1/ref%3Dsr%5F1%5F1/104-8819039-5717504#product-details

你这个东西什么时候要?
od 2004-09-14
  • 打赏
  • 举报
回复
另外问一下,关于正则表达式有没有特别经典的书?
od 2004-09-14
  • 打赏
  • 举报
回复
是的,思就是这个意

这个表达式是由操作者生成的,所以任何可能都是有的,甚至是中文,但这些由我自己处理就可以了

运算符用什么都可以,但要表达与/或的意思

我觉得这个要check的东西很多,如果你的时间不允许的话,可以不用做的特别健壮
registered 2004-09-14
  • 打赏
  • 举报
回复
我描述一下你看看对不对:

1.我最初得到
([asdf,123,ccc,true]∧[da,43,aaa,false]) ∧ ([fd,324,ddd,true]∧[asdf,43,eee,false])
2.检查表达式每个[]中的内容, 是[xxx,xxx,xxx]格式且xxx为字母或数字继续, 否则返回
3.根据每个[]单元中的 true/false 进行"与或运算"得到最终的一个 true/false


还有两个问题:
1.你的表达式中是否可以有空格(空格处理起来比较麻烦)
2.你的与或运算赋是否必须为"∧和∨", 是否可变为 "&和|" 或 "&&和||" 或 "AND和OR"
registered 2004-09-14
  • 打赏
  • 举报
回复

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Evaluator {
private int count;

private ArrayList list1 = new ArrayList(16);
private ArrayList list2 = new ArrayList(32);

private String[] unite(String[] s1, String[] s2) {
Object[] obj;
String[] result;
list1.clear();

for (int i = 0; i < s1.length; i++) {
if (!list1.contains(s1[i])) {
list1.add(s1[i]);
}
for (int j = 0; j < s2.length; j++) {
if (!s1[i].equals(s2[j]) && !list1.contains(s2[j])) {
list1.add(s2[j]);
}
}
}

obj = list1.toArray();
result = new String[obj.length];
for (int i = 0; i < obj.length; i++) {
result[i] = (String) obj[i];
}

return result;
}

private String[] intersect(String[] s1, String[] s2) {
Object[] obj;
String[] result;
list1.clear();

for (int i = 0; i < s1.length; i++) {
for (int j = 0; j < s2.length; j++) {
if (s1[i].equals(s2[j]) && !list1.contains(s1[i])) {
list1.add(s1[i]);
}
}
}

obj = list1.toArray();
result = new String[obj.length];
for (int i = 0; i < obj.length; i++) {
result[i] = (String) obj[i];
}

return result;
}

private void print(String[] s) {
for (int i = 0; i < s.length; i++) {
System.out.println(s[i]);
}
}

private String prepare(String example) {
StringBuffer sbuff = new StringBuffer(1024);
Pattern p_var = Pattern.compile("\\[(.*?)\\]");
Matcher m_var = p_var.matcher(example);

list2.clear();
while (m_var.find()) {
m_var.appendReplacement(sbuff, String.valueOf(count));
list2.add(m_var.group(1).split(","));
count++;
}
m_var.appendTail(sbuff);

return sbuff.toString();
}

private String[] calc(String example) {
String[] result;
String expression;
int operand_l;
int operand_r;
Pattern[] exp_p = {
Pattern.compile("\\((\\d)([&|])(\\d)\\)"),
Pattern.compile("(\\d)([|])(\\d)"),
Pattern.compile("(\\d)([&])(\\d)"),
};
Matcher exp_m;


expression = prepare(example);

for (int i = 0; i < exp_p.length; i++) {
exp_m = exp_p[i].matcher(expression);

for (; exp_m.find(); count++) {
operand_l = Integer.parseInt(exp_m.group(1));
operand_r = Integer.parseInt(exp_m.group(3));
if (exp_m.group(2).equals("&")) {
list2.add(intersect((String[]) list2.get(operand_l),
(String[]) list2.get(operand_r)));
} else {
list2.add(unite((String[]) list2.get(operand_l),
(String[]) list2.get(operand_r)));
}
expression = exp_m.replaceFirst(String.valueOf(count));
exp_m.reset(expression);
}
}

result = (String[]) list2.get(count - 1);

return result;
}

public static void main(String[] args) {
Evaluator eva = new Evaluator();
String example = "[123,345]&([123,234,345]&[123,345,456])|([234,sdf,dfg]|[987,654,321])";
String[] result = eva.calc(example);
eva.print(result);
}
}


根据我的理解这可能是你想要的解析
计算没有用后缀求值法, 用的是面向对象暴力法
注意: 表达式中英文混合使用可能会出错
od 2004-09-14
  • 打赏
  • 举报
回复
我的想法是去出与或符号,加入一个数组,然后find节点的正则表达式,没有报错

然后把节点替换成boolean的与或操作进行解析,最后返回true或false
od 2004-09-14
  • 打赏
  • 举报
回复
第一个问题:
变成字符串
([asdf,123,ccc]∧[da,43,aaa]) ∨ ([fd,324,ddd]∧[asdf,43,eee])... 如果解析后格 式正确的话,经处理会在子节点加一个字段true或false,变成这样的形式:
([asdf,123,ccc,true]∧[da,43,aaa,false]) ∨ ([fd,324,ddd,true]∧[asdf,43,eee,false])...
即只取每个节点里的true或false

第二个问题
处理不在本帖问题范围内


第三个问题
[asdf,123,ccc]这个的格式是固定的,[xxx,xxx,xxx],保证是字符和数字就可以
registered 2004-09-14
  • 打赏
  • 举报
回复
你这个问题也太复杂了

"if("(true && false) || (true && false)... ")
{
...
}
else..."
你是要把他变成字符串"(true && false) || (true && false)... "
还是变成布尔表达式 (true && false) || (true && false)
还是最终的一个布尔值 true / false ?

"([asdf,123,ccc]∧[da,43,aaa]) ∨ ([fd,324,ddd]∧[asdf,43,eee])... 如果解析后格式正确的话,经处理会在子节点加一个字段true或false,变成这样的形式:
([asdf,123,ccc,true]∧[da,43,aaa,false]) ∨ ([fd,324,ddd,true]∧[asdf,43,eee,false])..."
这个是你处理还是在本贴问题的范围之内?
如果是本贴问题,那怎么样才算格式正确?不正确怎么办?

"也就是说在保证子节点[asdf,123,ccc]格式正确的前提下,再保证替换子节点后的"(true && false) || (true && false)... "格式正确"
怎么样算格式正确,怎么样算不正确?
加载更多回复(13)

62,622

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧