Java 如何模式匹配左括号和后面的特定字符
简单地说,我试图找到一个模式,如果有一个方程有a(并检查之后是否有a+,或-或*或/,一个例子是Java 如何模式匹配左括号和后面的特定字符,java,regex,pattern-matching,Java,Regex,Pattern Matching,简单地说,我试图找到一个模式,如果有一个方程有a(并检查之后是否有a+,或-或*或/,一个例子是 4+3*(+2/1+3)*1试试这个解析器 number := [0-9]+ expression := '(', expression, ')', op | number, op op := '+', expression | '-', expression | '/', expression | '*', expression | epsilon 在伪EBNF中 public class E
4+3*(+2/1+3)*1试试这个解析器
number := [0-9]+
expression := '(', expression, ')', op | number, op
op := '+', expression | '-', expression | '/', expression | '*', expression | epsilon
在伪EBNF中
public class ExpressionParser {
private enum Type {
LB, RB, NUMBER, OP, END
}
private static class Token {
Type type;
String value;
int current;
public Token(Type type, String value, int current) {
super();
this.type = type;
this.value = value;
this.current = current;
}
@Override
public String toString() {
return "Token [type=" + type + ", value=" + value + ", current="
+ current + "]";
}
}
private static class Lexer {
private int current;
private String input;
public Lexer(String input) {
this.input = input;
}
private char getChar() {
return input.charAt(current++);
}
private void unputChar() {
current--;
}
private boolean hasNextChar() {
return current < input.length();
}
Token next() {
if (!hasNextChar()) {
return new Token(Type.END, "", current);
}
char c = getChar();
while (Character.isWhitespace(c)) {
c = getChar();
}
if (c == '(') {
return new Token(Type.LB, "(", current);
}
if (c == ')') {
return new Token(Type.RB, ")", current);
}
if (c == '+' || c == '-' || c == '*' || c == '/') {
return new Token(Type.OP, "" + c, current);
}
StringBuilder buffer = new StringBuilder();
while (hasNextChar()) {
c = getChar();
if (Character.isDigit(c)) {
buffer.append(c);
} else {
unputChar();
break;
}
}
return new Token(Type.NUMBER, buffer.toString(), current);
}
}
private static boolean match(Type type) {
return type == currentToken.type;
}
private static void consume(Type type) {
if (!match(type)) {
throw new RuntimeException(String.format("Should be %s is %s",
type.name(), currentToken.toString()));
}
currentToken = lexer.next();
}
private static void operation() {
if (match(Type.OP)) {
consume(Type.OP);
expression();
}
}
private static void expression() {
while (!match(Type.END)) {
if (match(Type.NUMBER)) {
consume(Type.NUMBER);
operation();
} else if (match(Type.LB)) {
consume(Type.LB);
expression();
consume(Type.RB);
operation();
} else {
break;
}
}
}
private static Lexer lexer;
private static Token currentToken;
private static void parse(String line) {
lexer = new Lexer(line);
currentToken = lexer.next();
try {
expression();
consume(Type.END);
System.out
.println(String.format("%s is a proper expression", line));
} catch (Exception e) {
System.out.println(String.format(
"%s is not a proper expression because %s", line,
e.getMessage()));
}
}
public static void main(String[] args) {
parse("4 + 3 * (+2/1 + 3) * 1");
parse("4 + 3 * (2/1+3) * 1");
parse("((((5/9)+6)-4)/1)");
parse("54-2*(23-2)/2");
parse("54-2*(-23-2)/2");
}
}
您的文本可以包含嵌套的括号吗?我尝试了模式y=Pattern.compile([(].*);模式z=Pattern.compile([(][+-/*].*));模式a=Pattern.compile(\([+-/*]);模式b=Pattern.compile((/().*))以及更多的变体combinations@Pshemo是的,我想是的。只要想想任何表达(((5/9)+6)-4)/1) 或者54-2*(23-2)/2,但在任何时候,它们都不能是左括号后面的任何符号,因此54-2*(-23-2)/2是错误的。我想说正则表达式不是适合这项工作的工具。你应该编写一个适当的递归解析器。你能解释更多吗?我仍在尝试学习这方面的知识:)
4 + 3 * (+2/1 + 3) * 1 is not a proper expression because Should be RB is Token [type=OP, value=+, current=10]
4 + 3 * (2/1+3) * 1 is a proper expression
((((5/9)+6)-4)/1) is a proper expression
54-2*(23-2)/2 is a proper expression
54-2*(-23-2)/2 is not a proper expression because Should be RB is Token [type=OP, value=-, current=7]