0

亲爱的开发者您好!

我是创建解析器的新手,只需要一点计算器语法。我正在使用 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 语句表现得像双值?

先感谢您!

4

0 回答 0