亲爱的开发者您好!
我是创建解析器的新手,只需要一点计算器语法。我正在使用 jparsec 并在 Github 上找到了计算器的示例。
我现在要做的就是在计算器中添加 IF 语句的可能性。
这是我的代码:
import org.jparsec.OperatorTable;
import org.jparsec.Parser;
import org.jparsec.Parsers;
import org.jparsec.Scanners;
import org.jparsec.Terminals;
import org.junit.jupiter.api.Test;
import static org.jparsec.Parsers.between;
import static org.jparsec.examples.java.parser.TerminalParser.phrase;
import static org.jparsec.examples.java.parser.TerminalParser.term;
import static org.junit.Assert.assertEquals;
import java.util.List;
public class Calculator {
static final Parser<Double> NUMBER =
Terminals.DecimalLiteral.PARSER.map(Double::valueOf);
private static final Terminals OPERATORS =
Terminals.operators(
//common Operators
"+", "-", "*", "/", "^", "%","[", "]",
//trigonometrical operators
"sin","cos","tan",
//logical operators
"=");
static final Parser<Void> IGNORED = Parsers.or(
Scanners.JAVA_LINE_COMMENT,
Scanners.JAVA_BLOCK_COMMENT,
Scanners.WHITESPACES).skipMany();
static final Parser<?> TOKENIZER =
Parsers.or(Terminals.DecimalLiteral.TOKENIZER, OPERATORS.tokenizer());
static Parser<?> term(String... names) {
return OPERATORS.token(names);
}
static final Parser<?> WHITESPACE_MUL = term("+", "-", "*", "/", "^").not();
static <T> Parser<T> op(String name, T value) {
return term(name).retn(value);
}
//Selbst zusammengebaut
private static Parser<String> beforeSemicolonExpression(){
return Parsers.between(
Scanners.WHITESPACES,
calculator(NUMBER).from(TOKENIZER, IGNORED).map(new java.util.function.Function<Double, String>(){
@Override
public String apply(Double t) {
return String.valueOf(t);
}
}),
Scanners.string(";"));
}
private static Parser<Double> ifStatement(){
return Parsers.between(
Scanners.string("if("),
beforeSemicolonExpression().times(3).map(new java.util.function.Function<List<String>, Double>(){
@Override
public Double apply(List<String> t) {
if(t.get(0).equals("1.0")) {
return Double.valueOf(t.get(1));
}else {
return Double.valueOf(t.get(2));
}
}
}),
Scanners.string(")"));
}
//Selbst zusammengebaut
static Parser<Double> calculator(Parser<Double> atom) {
Parser.Reference<Double> ref = Parser.newReference();
Parser<Double> unit = ref.lazy().between(term("["), term("]")).or(atom);
Parser<Double> parser = new OperatorTable<Double>()
.infixl(op("+", (l, r) -> l + r), 10)
.infixl(op("-", (l, r) -> l - r), 10)
.infixl(Parsers.or(term("*"), WHITESPACE_MUL).retn((l, r) -> l * r), 20)
.infixl(op("/", (l, r) -> l / r), 20)
.infixl(op("^", (l, r) -> CalculatorMethods.pow(l, CalculatorMethods.doubleToInteger(r))), 20)
.infixl(op("%", (l, r) -> l % r), 20)
.infixl(op("=", (l, r) -> CalculatorMethods.equalsForIfStatement(l, r)), 5)
.prefix(op("-", v -> -v), 40)
.prefix(op("sin", v -> CalculatorMethods.sinFunction(v)), 30)
.prefix(op("cos", v -> CalculatorMethods.cosFunction(v)), 30)
.prefix(op("tan", v -> CalculatorMethods.tanFunction(v)), 30)
.build(unit);
ref.set(parser);
return parser;
}
/*
public static final Parser<Double> CALCULATOR =
calculator(NUMBER).from(TOKENIZER, IGNORED);
*/
public static Parser<Double> calculation(){
//return calculator(NUMBER).from(TOKENIZER, IGNORED);
return Parsers.or(calculator(NUMBER).from(TOKENIZER, IGNORED), ifStatement());
}
@Test
public void test1() {
assertEquals((Object) 19.0, ifStatement().parse("if( 3; 1; 19;)"));
}
@Test
public void test2() {
assertEquals((Object) 1.0, ifStatement().parse("if( 1; 1; 19;)"));
}
@Test
public void test3() {
assertEquals((Object) 1.0, calculation().parse("1"));
}
@Test
public void test4() {
assertEquals((Object) 2.0, calculation().parse("1+2+3 = 2"));
}
@Test
public void test5() {
assertEquals((Object) 10.0, calculation().parse("if( 1 = 1; 1+2+3+4; 19;)"));
}
@Test
public void test6() {
assertEquals((Object) 11.0, calculation().parse("if( 1 = 1; 1+2+3+4; 19;) + 1"));
}
}
除最后一项外,所有测试均有效。任何人都知道如何让 if 语句表现得像双值?
先感谢您!